Initial commit

This commit is contained in:
Bassem Girgis
2018-12-20 17:34:07 -06:00
parent 7a2d899662
commit 81b4b9e273
34743 changed files with 5940233 additions and 0 deletions

View File

@@ -0,0 +1,295 @@
// (C) Copyright John Maddock 2006-8.
// 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_NTL_DIGAMMA
#define BOOST_MATH_NTL_DIGAMMA
#include <boost/math/tools/rational.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/lexical_cast.hpp>
namespace boost{ namespace math{ namespace detail{
template <class T>
T big_digamma_helper(T x)
{
static const T P[61] = {
boost::lexical_cast<T>("0.6660133691143982067148122682345055274952e81"),
boost::lexical_cast<T>("0.6365271516829242456324234577164675383137e81"),
boost::lexical_cast<T>("0.2991038873096202943405966144203628966976e81"),
boost::lexical_cast<T>("0.9211116495503170498076013367421231351115e80"),
boost::lexical_cast<T>("0.2090792764676090716286400360584443891749e80"),
boost::lexical_cast<T>("0.3730037777359591428226035156377978092809e79"),
boost::lexical_cast<T>("0.5446396536956682043376492370432031543834e78"),
boost::lexical_cast<T>("0.6692523966335177847425047827449069256345e77"),
boost::lexical_cast<T>("0.7062543624100864681625612653756619116848e76"),
boost::lexical_cast<T>("0.6499914905966283735005256964443226879158e75"),
boost::lexical_cast<T>("0.5280364564853225211197557708655426736091e74"),
boost::lexical_cast<T>("0.3823205608981176913075543599005095206953e73"),
boost::lexical_cast<T>("0.2486733714214237704739129972671154532415e72"),
boost::lexical_cast<T>("0.1462562139602039577983434547171318011675e71"),
boost::lexical_cast<T>("0.7821169065036815012381267259559910324285e69"),
boost::lexical_cast<T>("0.3820552182348155468636157988764435365078e68"),
boost::lexical_cast<T>("0.1711618296983598244658239925535632505062e67"),
boost::lexical_cast<T>("0.7056661618357643731419080738521475204245e65"),
boost::lexical_cast<T>("0.2685246896473614017356264531791459936036e64"),
boost::lexical_cast<T>("0.9455168125599643085283071944864977592391e62"),
boost::lexical_cast<T>("0.3087541626972538362237309145177486236219e61"),
boost::lexical_cast<T>("0.9367928873352980208052601301625005737407e59"),
boost::lexical_cast<T>("0.2645306130689794942883818547314327466007e58"),
boost::lexical_cast<T>("0.6961815141171454309161007351079576190079e56"),
boost::lexical_cast<T>("0.1709637824471794552313802669803885946843e55"),
boost::lexical_cast<T>("0.3921553258481531526663112728778759311158e53"),
boost::lexical_cast<T>("0.8409006354449988687714450897575728228696e51"),
boost::lexical_cast<T>("0.1686755204461325935742097669030363344927e50"),
boost::lexical_cast<T>("0.3166653542877070999007425197729038754254e48"),
boost::lexical_cast<T>("0.5566029092358215049069560272835654229637e46"),
boost::lexical_cast<T>("0.9161766287916328133080586672953875116242e44"),
boost::lexical_cast<T>("1412317772330871298317974693514430627922000"),
boost::lexical_cast<T>("20387991986727877473732570146112459874790"),
boost::lexical_cast<T>("275557928713904105182512535678580359839.3"),
boost::lexical_cast<T>("3485719851040516559072031256589598330.723"),
boost::lexical_cast<T>("41247046743564028399938106707656877.40859"),
boost::lexical_cast<T>("456274078125709314602601667471879.0147312"),
boost::lexical_cast<T>("4714450683242899367025707077155.310613012"),
boost::lexical_cast<T>("45453933537925041680009544258.75073849996"),
boost::lexical_cast<T>("408437900487067278846361972.302331241052"),
boost::lexical_cast<T>("3415719344386166273085838.705771571751035"),
boost::lexical_cast<T>("26541502879185876562320.93134691487351145"),
boost::lexical_cast<T>("191261415065918713661.1571433274648417668"),
boost::lexical_cast<T>("1275349770108718421.645275944284937551702"),
boost::lexical_cast<T>("7849171120971773.318910987434906905704272"),
boost::lexical_cast<T>("44455946386549.80866460312682983576538056"),
boost::lexical_cast<T>("230920362395.3198137186361608905136598046"),
boost::lexical_cast<T>("1095700096.240863858624279930600654130254"),
boost::lexical_cast<T>("4727085.467506050153744334085516289728134"),
boost::lexical_cast<T>("18440.75118859447173303252421991479005424"),
boost::lexical_cast<T>("64.62515887799460295677071749181651317052"),
boost::lexical_cast<T>("0.201851568864688406206528472883512147547"),
boost::lexical_cast<T>("0.0005565091674187978029138500039504078098143"),
boost::lexical_cast<T>("0.1338097668312907986354698683493366559613e-5"),
boost::lexical_cast<T>("0.276308225077464312820179030238305271638e-8"),
boost::lexical_cast<T>("0.4801582970473168520375942100071070575043e-11"),
boost::lexical_cast<T>("0.6829184144212920949740376186058541800175e-14"),
boost::lexical_cast<T>("0.7634080076358511276617829524639455399182e-17"),
boost::lexical_cast<T>("0.6290035083727140966418512608156646142409e-20"),
boost::lexical_cast<T>("0.339652245667538733044036638506893821352e-23"),
boost::lexical_cast<T>("0.9017518064256388530773585529891677854909e-27")
};
static const T Q[61] = {
boost::lexical_cast<T>("0"),
boost::lexical_cast<T>("0.1386831185456898357379390197203894063459e81"),
boost::lexical_cast<T>("0.6467076379487574703291056110838151259438e81"),
boost::lexical_cast<T>("0.1394967823848615838336194279565285465161e82"),
boost::lexical_cast<T>("0.1872927317344192945218570366455046340458e82"),
boost::lexical_cast<T>("0.1772461045338946243584650759986310355937e82"),
boost::lexical_cast<T>("0.1267294892200258648315971144069595555118e82"),
boost::lexical_cast<T>("0.7157764838362416821508872117623058626589e81"),
boost::lexical_cast<T>("0.329447266909948668265277828268378274513e81"),
boost::lexical_cast<T>("0.1264376077317689779509250183194342571207e81"),
boost::lexical_cast<T>("0.4118230304191980787640446056583623228873e80"),
boost::lexical_cast<T>("0.1154393529762694616405952270558316515261e80"),
boost::lexical_cast<T>("0.281655612889423906125295485693696744275e79"),
boost::lexical_cast<T>("0.6037483524928743102724159846414025482077e78"),
boost::lexical_cast<T>("0.1145927995397835468123576831800276999614e78"),
boost::lexical_cast<T>("0.1938624296151985600348534009382865995154e77"),
boost::lexical_cast<T>("0.293980925856227626211879961219188406675e76"),
boost::lexical_cast<T>("0.4015574518216966910319562902099567437832e75"),
boost::lexical_cast<T>("0.4961475457509727343545565970423431880907e74"),
boost::lexical_cast<T>("0.5565482348278933960215521991000378896338e73"),
boost::lexical_cast<T>("0.5686112924615820754631098622770303094938e72"),
boost::lexical_cast<T>("0.5305988545844796293285410303747469932856e71"),
boost::lexical_cast<T>("0.4533363413802585060568537458067343491358e70"),
boost::lexical_cast<T>("0.3553932059473516064068322757331575565718e69"),
boost::lexical_cast<T>("0.2561198565218704414618802902533972354203e68"),
boost::lexical_cast<T>("0.1699519313292900324098102065697454295572e67"),
boost::lexical_cast<T>("0.1039830160862334505389615281373574959236e66"),
boost::lexical_cast<T>("0.5873082967977428281000961954715372504986e64"),
boost::lexical_cast<T>("0.3065255179030575882202133042549783442446e63"),
boost::lexical_cast<T>("0.1479494813481364701208655943688307245459e62"),
boost::lexical_cast<T>("0.6608150467921598615495180659808895663164e60"),
boost::lexical_cast<T>("0.2732535313770902021791888953487787496976e59"),
boost::lexical_cast<T>("0.1046402297662493314531194338414508049069e58"),
boost::lexical_cast<T>("0.3711375077192882936085049147920021549622e56"),
boost::lexical_cast<T>("0.1219154482883895482637944309702972234576e55"),
boost::lexical_cast<T>("0.3708359374149458741391374452286837880162e53"),
boost::lexical_cast<T>("0.1044095509971707189716913168889769471468e52"),
boost::lexical_cast<T>("0.271951506225063286130946773813524945052e50"),
boost::lexical_cast<T>("0.6548016291215163843464133978454065823866e48"),
boost::lexical_cast<T>("0.1456062447610542135403751730809295219344e47"),
boost::lexical_cast<T>("0.2986690175077969760978388356833006028929e45"),
boost::lexical_cast<T>("5643149706574013350061247429006443326844000"),
boost::lexical_cast<T>("98047545414467090421964387960743688053480"),
boost::lexical_cast<T>("1563378767746846395507385099301468978550"),
boost::lexical_cast<T>("22823360528584500077862274918382796495"),
boost::lexical_cast<T>("304215527004115213046601295970388750"),
boost::lexical_cast<T>("3690289075895685793844344966820325"),
boost::lexical_cast<T>("40584512015702371433911456606050"),
boost::lexical_cast<T>("402834190897282802772754873905"),
boost::lexical_cast<T>("3589522158493606918146495750"),
boost::lexical_cast<T>("28530557707503483723634725"),
boost::lexical_cast<T>("200714561335055753000730"),
boost::lexical_cast<T>("1237953783437761888641"),
boost::lexical_cast<T>("6614698701445762950"),
boost::lexical_cast<T>("30155495647727505"),
boost::lexical_cast<T>("114953256021450"),
boost::lexical_cast<T>("356398020013"),
boost::lexical_cast<T>("863113950"),
boost::lexical_cast<T>("1531345"),
boost::lexical_cast<T>("1770"),
boost::lexical_cast<T>("1")
};
static const T PD[60] = {
boost::lexical_cast<T>("0.6365271516829242456324234577164675383137e81"),
2*boost::lexical_cast<T>("0.2991038873096202943405966144203628966976e81"),
3*boost::lexical_cast<T>("0.9211116495503170498076013367421231351115e80"),
4*boost::lexical_cast<T>("0.2090792764676090716286400360584443891749e80"),
5*boost::lexical_cast<T>("0.3730037777359591428226035156377978092809e79"),
6*boost::lexical_cast<T>("0.5446396536956682043376492370432031543834e78"),
7*boost::lexical_cast<T>("0.6692523966335177847425047827449069256345e77"),
8*boost::lexical_cast<T>("0.7062543624100864681625612653756619116848e76"),
9*boost::lexical_cast<T>("0.6499914905966283735005256964443226879158e75"),
10*boost::lexical_cast<T>("0.5280364564853225211197557708655426736091e74"),
11*boost::lexical_cast<T>("0.3823205608981176913075543599005095206953e73"),
12*boost::lexical_cast<T>("0.2486733714214237704739129972671154532415e72"),
13*boost::lexical_cast<T>("0.1462562139602039577983434547171318011675e71"),
14*boost::lexical_cast<T>("0.7821169065036815012381267259559910324285e69"),
15*boost::lexical_cast<T>("0.3820552182348155468636157988764435365078e68"),
16*boost::lexical_cast<T>("0.1711618296983598244658239925535632505062e67"),
17*boost::lexical_cast<T>("0.7056661618357643731419080738521475204245e65"),
18*boost::lexical_cast<T>("0.2685246896473614017356264531791459936036e64"),
19*boost::lexical_cast<T>("0.9455168125599643085283071944864977592391e62"),
20*boost::lexical_cast<T>("0.3087541626972538362237309145177486236219e61"),
21*boost::lexical_cast<T>("0.9367928873352980208052601301625005737407e59"),
22*boost::lexical_cast<T>("0.2645306130689794942883818547314327466007e58"),
23*boost::lexical_cast<T>("0.6961815141171454309161007351079576190079e56"),
24*boost::lexical_cast<T>("0.1709637824471794552313802669803885946843e55"),
25*boost::lexical_cast<T>("0.3921553258481531526663112728778759311158e53"),
26*boost::lexical_cast<T>("0.8409006354449988687714450897575728228696e51"),
27*boost::lexical_cast<T>("0.1686755204461325935742097669030363344927e50"),
28*boost::lexical_cast<T>("0.3166653542877070999007425197729038754254e48"),
29*boost::lexical_cast<T>("0.5566029092358215049069560272835654229637e46"),
30*boost::lexical_cast<T>("0.9161766287916328133080586672953875116242e44"),
31*boost::lexical_cast<T>("1412317772330871298317974693514430627922000"),
32*boost::lexical_cast<T>("20387991986727877473732570146112459874790"),
33*boost::lexical_cast<T>("275557928713904105182512535678580359839.3"),
34*boost::lexical_cast<T>("3485719851040516559072031256589598330.723"),
35*boost::lexical_cast<T>("41247046743564028399938106707656877.40859"),
36*boost::lexical_cast<T>("456274078125709314602601667471879.0147312"),
37*boost::lexical_cast<T>("4714450683242899367025707077155.310613012"),
38*boost::lexical_cast<T>("45453933537925041680009544258.75073849996"),
39*boost::lexical_cast<T>("408437900487067278846361972.302331241052"),
40*boost::lexical_cast<T>("3415719344386166273085838.705771571751035"),
41*boost::lexical_cast<T>("26541502879185876562320.93134691487351145"),
42*boost::lexical_cast<T>("191261415065918713661.1571433274648417668"),
43*boost::lexical_cast<T>("1275349770108718421.645275944284937551702"),
44*boost::lexical_cast<T>("7849171120971773.318910987434906905704272"),
45*boost::lexical_cast<T>("44455946386549.80866460312682983576538056"),
46*boost::lexical_cast<T>("230920362395.3198137186361608905136598046"),
47*boost::lexical_cast<T>("1095700096.240863858624279930600654130254"),
48*boost::lexical_cast<T>("4727085.467506050153744334085516289728134"),
49*boost::lexical_cast<T>("18440.75118859447173303252421991479005424"),
50*boost::lexical_cast<T>("64.62515887799460295677071749181651317052"),
51*boost::lexical_cast<T>("0.201851568864688406206528472883512147547"),
52*boost::lexical_cast<T>("0.0005565091674187978029138500039504078098143"),
53*boost::lexical_cast<T>("0.1338097668312907986354698683493366559613e-5"),
54*boost::lexical_cast<T>("0.276308225077464312820179030238305271638e-8"),
55*boost::lexical_cast<T>("0.4801582970473168520375942100071070575043e-11"),
56*boost::lexical_cast<T>("0.6829184144212920949740376186058541800175e-14"),
57*boost::lexical_cast<T>("0.7634080076358511276617829524639455399182e-17"),
58*boost::lexical_cast<T>("0.6290035083727140966418512608156646142409e-20"),
59*boost::lexical_cast<T>("0.339652245667538733044036638506893821352e-23"),
60*boost::lexical_cast<T>("0.9017518064256388530773585529891677854909e-27")
};
static const T QD[60] = {
boost::lexical_cast<T>("0.1386831185456898357379390197203894063459e81"),
2*boost::lexical_cast<T>("0.6467076379487574703291056110838151259438e81"),
3*boost::lexical_cast<T>("0.1394967823848615838336194279565285465161e82"),
4*boost::lexical_cast<T>("0.1872927317344192945218570366455046340458e82"),
5*boost::lexical_cast<T>("0.1772461045338946243584650759986310355937e82"),
6*boost::lexical_cast<T>("0.1267294892200258648315971144069595555118e82"),
7*boost::lexical_cast<T>("0.7157764838362416821508872117623058626589e81"),
8*boost::lexical_cast<T>("0.329447266909948668265277828268378274513e81"),
9*boost::lexical_cast<T>("0.1264376077317689779509250183194342571207e81"),
10*boost::lexical_cast<T>("0.4118230304191980787640446056583623228873e80"),
11*boost::lexical_cast<T>("0.1154393529762694616405952270558316515261e80"),
12*boost::lexical_cast<T>("0.281655612889423906125295485693696744275e79"),
13*boost::lexical_cast<T>("0.6037483524928743102724159846414025482077e78"),
14*boost::lexical_cast<T>("0.1145927995397835468123576831800276999614e78"),
15*boost::lexical_cast<T>("0.1938624296151985600348534009382865995154e77"),
16*boost::lexical_cast<T>("0.293980925856227626211879961219188406675e76"),
17*boost::lexical_cast<T>("0.4015574518216966910319562902099567437832e75"),
18*boost::lexical_cast<T>("0.4961475457509727343545565970423431880907e74"),
19*boost::lexical_cast<T>("0.5565482348278933960215521991000378896338e73"),
20*boost::lexical_cast<T>("0.5686112924615820754631098622770303094938e72"),
21*boost::lexical_cast<T>("0.5305988545844796293285410303747469932856e71"),
22*boost::lexical_cast<T>("0.4533363413802585060568537458067343491358e70"),
23*boost::lexical_cast<T>("0.3553932059473516064068322757331575565718e69"),
24*boost::lexical_cast<T>("0.2561198565218704414618802902533972354203e68"),
25*boost::lexical_cast<T>("0.1699519313292900324098102065697454295572e67"),
26*boost::lexical_cast<T>("0.1039830160862334505389615281373574959236e66"),
27*boost::lexical_cast<T>("0.5873082967977428281000961954715372504986e64"),
28*boost::lexical_cast<T>("0.3065255179030575882202133042549783442446e63"),
29*boost::lexical_cast<T>("0.1479494813481364701208655943688307245459e62"),
30*boost::lexical_cast<T>("0.6608150467921598615495180659808895663164e60"),
31*boost::lexical_cast<T>("0.2732535313770902021791888953487787496976e59"),
32*boost::lexical_cast<T>("0.1046402297662493314531194338414508049069e58"),
33*boost::lexical_cast<T>("0.3711375077192882936085049147920021549622e56"),
34*boost::lexical_cast<T>("0.1219154482883895482637944309702972234576e55"),
35*boost::lexical_cast<T>("0.3708359374149458741391374452286837880162e53"),
36*boost::lexical_cast<T>("0.1044095509971707189716913168889769471468e52"),
37*boost::lexical_cast<T>("0.271951506225063286130946773813524945052e50"),
38*boost::lexical_cast<T>("0.6548016291215163843464133978454065823866e48"),
39*boost::lexical_cast<T>("0.1456062447610542135403751730809295219344e47"),
40*boost::lexical_cast<T>("0.2986690175077969760978388356833006028929e45"),
41*boost::lexical_cast<T>("5643149706574013350061247429006443326844000"),
42*boost::lexical_cast<T>("98047545414467090421964387960743688053480"),
43*boost::lexical_cast<T>("1563378767746846395507385099301468978550"),
44*boost::lexical_cast<T>("22823360528584500077862274918382796495"),
45*boost::lexical_cast<T>("304215527004115213046601295970388750"),
46*boost::lexical_cast<T>("3690289075895685793844344966820325"),
47*boost::lexical_cast<T>("40584512015702371433911456606050"),
48*boost::lexical_cast<T>("402834190897282802772754873905"),
49*boost::lexical_cast<T>("3589522158493606918146495750"),
50*boost::lexical_cast<T>("28530557707503483723634725"),
51*boost::lexical_cast<T>("200714561335055753000730"),
52*boost::lexical_cast<T>("1237953783437761888641"),
53*boost::lexical_cast<T>("6614698701445762950"),
54*boost::lexical_cast<T>("30155495647727505"),
55*boost::lexical_cast<T>("114953256021450"),
56*boost::lexical_cast<T>("356398020013"),
57*boost::lexical_cast<T>("863113950"),
58*boost::lexical_cast<T>("1531345"),
59*boost::lexical_cast<T>("1770"),
60*boost::lexical_cast<T>("1")
};
static const double g = 63.192152;
T zgh = x + g - 0.5;
T result = (x - 0.5) / zgh;
result += log(zgh);
result += tools::evaluate_polynomial(PD, x) / tools::evaluate_polynomial(P, x);
result -= tools::evaluate_polynomial(QD, x) / tools::evaluate_polynomial(Q, x);
result -= 1;
return result;
}
template <class T>
T big_digamma(T x)
{
BOOST_MATH_STD_USING
if(x < 0)
{
return big_digamma_helper(static_cast<T>(1-x)) + constants::pi<T>() / tan(constants::pi<T>() * (1-x));
}
return big_digamma_helper(x);
}
}}}
#endif // include guard

View File

@@ -0,0 +1,777 @@
// (C) Copyright John Maddock 2006-8.
// 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_BIG_LANCZOS_HPP
#define BOOST_BIG_LANCZOS_HPP
#include <boost/math/special_functions/lanczos.hpp>
namespace boost{ namespace math{ namespace lanczos{
//
// Lanczos Coefficients for N=13 G=13.144565
// Max experimental error (with arbitary precision arithmetic) 9.2213e-23
// Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 23 2006
//
typedef lanczos13 lanczos13UDT;
//
// Lanczos Coefficients for N=22 G=22.61891
// Max experimental error (with arbitary precision arithmetic) 2.9524e-38
// Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 23 2006
//
struct lanczos22UDT : public mpl::int_<120>
{
//
// Produces slightly better than 128-bit long-double precision when
// evaluated at higher precision:
//
template <class T>
static T lanczos_sum(const T& z)
{
lanczos_initializer<lanczos22UDT, T>::force_instantiate(); // Ensure our constants get initialized before main()
static const T num[22] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 46198410803245094237463011094.12173081986)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 43735859291852324413622037436.321513777)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 19716607234435171720534556386.97481377748)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 5629401471315018442177955161.245623932129)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1142024910634417138386281569.245580222392)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 175048529315951173131586747.695329230778)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 21044290245653709191654675.41581372963167)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 2033001410561031998451380.335553678782601)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 160394318862140953773928.8736211601848891)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 10444944438396359705707.48957290388740896)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 565075825801617290121.1466393747967538948)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 25475874292116227538.99448534450411942597)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 957135055846602154.6720835535232270205725)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 29874506304047462.23662392445173880821515)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 769651310384737.2749087590725764959689181)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 16193289100889.15989633624378404096011797)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 273781151680.6807433264462376754578933261)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 3630485900.32917021712188739762161583295)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 36374352.05577334277856865691538582936484)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 258945.7742115532455441786924971194951043)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1167.501919472435718934219997431551246996)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 2.50662827463100050241576528481104525333))
};
static const T denom[22] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 2432902008176640000.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 8752948036761600000.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 13803759753640704000.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 12870931245150988800.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 8037811822645051776.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 3599979517947607200.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1206647803780373360.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 311333643161390640.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 63030812099294896.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 10142299865511450.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1307535010540395.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 135585182899530.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 11310276995381.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 756111184500.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 40171771630.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1672280820.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 53327946.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1256850.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 20615.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 210.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1.0))
};
return boost::math::tools::evaluate_rational(num, denom, z);
}
template <class T>
static T lanczos_sum_expG_scaled(const T& z)
{
lanczos_initializer<lanczos22UDT, T>::force_instantiate(); // Ensure our constants get initialized before main()
static const T num[22] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 6939996264376682180.277485395074954356211)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 6570067992110214451.87201438870245659384)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 2961859037444440551.986724631496417064121)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 845657339772791245.3541226499766163431651)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 171556737035449095.2475716923888737881837)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 26296059072490867.7822441885603400926007)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 3161305619652108.433798300149816829198706)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 305400596026022.4774396904484542582526472)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 24094681058862.55120507202622377623528108)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1569055604375.919477574824168939428328839)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 84886558909.02047889339710230696942513159)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 3827024985.166751989686050643579753162298)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 143782298.9273215199098728674282885500522)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 4487794.24541641841336786238909171265944)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 115618.2025760830513505888216285273541959)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 2432.580773108508276957461757328744780439)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 41.12782532742893597168530008461874360191)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.5453771709477689805460179187388702295792)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.005464211062612080347167337964166505282809)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.388992321263586767037090706042788910953e-4)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.1753839324538447655939518484052327068859e-6)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.3765495513732730583386223384116545391759e-9))
};
static const T denom[22] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 2432902008176640000.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 8752948036761600000.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 13803759753640704000.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 12870931245150988800.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 8037811822645051776.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 3599979517947607200.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1206647803780373360.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 311333643161390640.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 63030812099294896.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 10142299865511450.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1307535010540395.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 135585182899530.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 11310276995381.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 756111184500.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 40171771630.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1672280820.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 53327946.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1256850.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 20615.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 210.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1.0))
};
return boost::math::tools::evaluate_rational(num, denom, z);
}
template<class T>
static T lanczos_sum_near_1(const T& dz)
{
lanczos_initializer<lanczos22UDT, T>::force_instantiate(); // Ensure our constants get initialized before main()
static const T d[21] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 8.318998691953337183034781139546384476554)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -63.15415991415959158214140353299240638675)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 217.3108224383632868591462242669081540163)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -448.5134281386108366899784093610397354889)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 619.2903759363285456927248474593012711346)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -604.1630177420625418522025080080444177046)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 428.8166750424646119935047118287362193314)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -224.6988753721310913866347429589434550302)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 87.32181627555510833499451817622786940961)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -25.07866854821128965662498003029199058098)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 5.264398125689025351448861011657789005392)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -0.792518936256495243383586076579921559914)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.08317448364744713773350272460937904691566)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -0.005845345166274053157781068150827567998882)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.0002599412126352082483326238522490030412391)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -0.6748102079670763884917431338234783496303e-5)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.908824383434109002762325095643458603605e-7)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -0.5299325929309389890892469299969669579725e-9)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.994306085859549890267983602248532869362e-12)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -0.3499893692975262747371544905820891835298e-15)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.7260746353663365145454867069182884694961e-20)),
};
T result = 0;
for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k)
{
result += (-d[k-1]*dz)/(k*dz + k*k);
}
return result;
}
template<class T>
static T lanczos_sum_near_2(const T& dz)
{
static const T d[21] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 75.39272007105208086018421070699575462226)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -572.3481967049935412452681346759966390319)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 1969.426202741555335078065370698955484358)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -4064.74968778032030891520063865996757519)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 5612.452614138013929794736248384309574814)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -5475.357667500026172903620177988213902339)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 3886.243614216111328329547926490398103492)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -2036.382026072125407192448069428134470564)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 791.3727954936062108045551843636692287652)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -227.2808432388436552794021219198885223122)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 47.70974355562144229897637024320739257284)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -7.182373807798293545187073539819697141572)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.7537866989631514559601547530490976100468)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -0.05297470142240154822658739758236594717787)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.00235577330936380542539812701472320434133)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -0.6115613067659273118098229498679502138802e-4)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.8236417010170941915758315020695551724181e-6)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -0.4802628430993048190311242611330072198089e-8)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.9011113376981524418952720279739624707342e-11)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, -0.3171854152689711198382455703658589996796e-14)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 120, 0.6580207998808093935798753964580596673177e-19)),
};
T result = 0;
T z = dz + 2;
for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k)
{
result += (-d[k-1]*dz)/(z + k*z + k*k - 1);
}
return result;
}
static double g(){ return 22.61890999999999962710717227309942245483; }
};
//
// Lanczos Coefficients for N=31 G=32.08067
// Max experimental error (with arbitary precision arithmetic) 0.162e-52
// Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at May 9 2006
//
struct lanczos31UDT
{
template <class T>
static T lanczos_sum(const T& z)
{
lanczos_initializer<lanczos31UDT, T>::force_instantiate(); // Ensure our constants get initialized before main()
static const T num[31] = {
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.2579646553333513328235723061836959833277e46)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.2444796504337453845497419271639377138264e46)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.1119885499016017172212179730662673475329e46)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.3301983829072723658949204487793889113715e45)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.7041171040503851585152895336505379417066e44)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.1156687509001223855125097826246939403504e44)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1522559363393940883866575697565974893306000)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 164914363507650839510801418717701057005700)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 14978522943127593263654178827041568394060)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1156707153701375383907746879648168666774)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 76739431129980851159755403434593664173.2)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 4407916278928188620282281495575981079.306)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 220487883931812802092792125175269667.3004)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 9644828280794966468052381443992828.433924)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 369996467042247229310044531282837.6549068)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 12468380890717344610932904378961.13494291)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 369289245210898235894444657859.0529720075)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 9607992460262594951559461829.34885209022)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 219225935074853412540086410.981421315799)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 4374309943598658046326340.720767382079549)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 76008779092264509404014.10530947173485581)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1143503533822162444712.335663112617754987)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 14779233719977576920.37884890049671578409)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 162409028440678302.9992838032166348069916)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1496561553388385.733407609544964535634135)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 11347624460661.81008311053190661436107043)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 68944915931.32004991941950530448472223832)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 322701221.6391432296123937035480931903651)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1092364.213992634267819050120261755371294)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 2380.151399852411512711176940867823024864)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 2.506628274631000502415765284811045253007)),
};
static const T denom[31] = {
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.8841761993739701954543616e31)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.3502799997985980526649278464e32)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.622621928420356134910574592e32)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 66951000306085302338993639424000)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 49361465831621147825759587123200)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 26751280755793398822580822142976)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 11139316913434780466101123891200)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 3674201658710345201899117607040)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 981347603630155088295475765440)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 215760462268683520394805979744)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 39539238727270799376544542000)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 6097272817323042122728617800)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 796974693974455191377937300)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 88776380550648116217781890)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 8459574446076318147830625)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 691254538651580660999025)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 48487623689430693038025)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 2918939500751087661105)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 150566737512021319125)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 6634460278534540725)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 248526574856284725)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 7860403394108265)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 207912996295875)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 4539323721075)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 80328850875)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1122686019)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 11921175)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 90335)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 435)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1)),
};
return boost::math::tools::evaluate_rational(num, denom, z, 31);
}
template <class T>
static T lanczos_sum_expG_scaled(const T& z)
{
lanczos_initializer<lanczos31UDT, T>::force_instantiate(); // Ensure our constants get initialized before main()
static const T num[31] = {
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 30137154810677525966583148469478.52374216)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 28561746428637727032849890123131.36314653)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 13083250730789213354063781611435.74046294)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 3857598154697777600846539129354.783647)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 822596651552555685068015316144.0952185852)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 135131964033213842052904200372.039133532)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 17787555889683709693655685146.19771358863)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1926639793777927562221423874.149673297196)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 174989113988888477076973808.6991839697774)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 13513425905835560387095425.01158383184045)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 896521313378762433091075.1446749283094845)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 51496223433749515758124.71524415105430686)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 2575886794780078381228.37205955912263407)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 112677328855422964200.4155776009524490958)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 4322545967487943330.625233358130724324796)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 145663957202380774.0362027607207590519723)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 4314283729473470.686566233465428332496534)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 112246988185485.8877916434026906290603878)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 2561143864972.040563435178307062626388193)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 51103611767.9626550674442537989885239605)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 887985348.0369447209508500133077232094491)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 13359172.3954672607019822025834072685839)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 172660.8841147568768783928167105965064459)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1897.370795407433013556725714874693719617)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 17.48383210090980598861217644749573257178)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.1325705316732132940835251054350153028901)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.0008054605783673449641889260501816356090452)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.377001130700104515644336869896819162464e-5)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.1276172868883867038813825443204454996531e-7)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.2780651912081116274907381023821492811093e-10)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.2928410648650955854121639682890739211234e-13)),
};
static const T denom[31] = {
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.8841761993739701954543616e31)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.3502799997985980526649278464e32)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.622621928420356134910574592e32)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 66951000306085302338993639424000)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 49361465831621147825759587123200)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 26751280755793398822580822142976)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 11139316913434780466101123891200)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 3674201658710345201899117607040)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 981347603630155088295475765440)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 215760462268683520394805979744)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 39539238727270799376544542000)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 6097272817323042122728617800)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 796974693974455191377937300)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 88776380550648116217781890)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 8459574446076318147830625)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 691254538651580660999025)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 48487623689430693038025)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 2918939500751087661105)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 150566737512021319125)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 6634460278534540725)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 248526574856284725)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 7860403394108265)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 207912996295875)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 4539323721075)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 80328850875)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1122686019)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 11921175)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 90335)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 435)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1)),
};
return boost::math::tools::evaluate_rational(num, denom, z, 31);
}
template<class T>
static T lanczos_sum_near_1(const T& dz)
{
lanczos_initializer<lanczos31UDT, T>::force_instantiate(); // Ensure our constants get initialized before main()
static const T d[30] = {
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 11.80038544942943603508206880307972596807)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -130.6355975335626214564236363322099481079)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 676.2177719145993049893392276809256538927)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -2174.724497783850503069990936574060452057)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 4869.877180638131076410069103742986502022)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -8065.744271864238179992762265472478229172)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 10245.03825618572106228191509520638651539)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -10212.83902362683215459850403668669647192)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 8110.289185383288952562767679576754140336)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -5179.310892558291062401828964000776095156)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 2673.987492589052370230989109591011091273)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -1118.342574651205183051884250033505609141)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 378.5812742511620662650096436471920295596)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -103.3725999812126067084828735543906768961)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 22.62913974335996321848099677797888917792)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -3.936414819950859548507275533569588041446)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.5376818198843817355682124535902641644854)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.0567827903603478957483409124122554243201)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.004545544993648879420352693271088478106482)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.0002689795568951033950042375135970897959935)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.1139493459006846530734617710847103572122e-4)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.3316581197839213921885210451302820192794e-6)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.6285613334898374028443777562554713906213e-8)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.7222145115734409070310317999856424167091e-10)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.4562976983547274766890241815002584238219e-12)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.1380593023819058919640038942493212141072e-14)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.1629663871586410129307496385264268190679e-17)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.5429994291916548849493889660077076739993e-21)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.2922682842441892106795386303084661338957e-25)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.8456967065309046044689041041336866118459e-31)),
};
T result = 0;
for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k)
{
result += (-d[k-1]*dz)/(k*dz + k*k);
}
return result;
}
template<class T>
static T lanczos_sum_near_2(const T& dz)
{
lanczos_initializer<lanczos31UDT, T>::force_instantiate(); // Ensure our constants get initialized before main()
static const T d[30] = {
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 147.9979641587472136175636384176549713358)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -1638.404318611773924210055619836375434296)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 8480.981744216135641122944743711911653273)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -27274.93942104458448200467097634494071176)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 61076.98019918759324489193232276937262854)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -101158.8762737154296509560513952101409264)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 128491.1252383947174824913796141607174379)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -128087.2892038336581928787480535905496026)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 101717.5492545853663296795562084430123258)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -64957.8330410311808907869707511362206858)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 33536.59139229792478811870738772305570317)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -14026.01847115365926835980820243003785821)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 4748.087094096186515212209389240715050212)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -1296.477510211815971152205100242259733245)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 283.8099337545793198947620951499958085157)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -49.36969067101255103452092297769364837753)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 6.743492833270653628580811118017061581404)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.7121578704864048548351804794951487823626)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.0570092738016915476694118877057948681298)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.003373485297696102660302960722607722438643)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.0001429128843527532859999752593761934089751)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.41595867130858508233493767243236888636e-5)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.7883284669307241040059778207492255409785e-7)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.905786322462384670803148223703187214379e-9)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.5722790216999820323272452464661250331451e-11)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.1731510870832349779315841757234562309727e-13)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.2043890314358438601429048378015983874378e-16)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.6810185176079344204740000170500311171065e-20)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.3665567641131713928114853776588342403919e-24)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.1060655106553177007425710511436497259484e-29)),
};
T result = 0;
T z = dz + 2;
for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k)
{
result += (-d[k-1]*dz)/(z + k*z + k*k - 1);
}
return result;
}
static double g(){ return 32.08066999999999779902282170951366424561; }
};
//
// Lanczos Coefficients for N=61 G=63.192152
// Max experimental error (with 1000-bit precision arithmetic) 3.740e-113
// Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 12 2006
//
struct lanczos61UDT
{
template <class T>
static T lanczos_sum(const T& z)
{
lanczos_initializer<lanczos61UDT, T>::force_instantiate(); // Ensure our constants get initialized before main()
using namespace boost;
static const T d[61] = {
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 2.50662827463100050241576528481104525300698674060993831662992357634229365460784197494659584)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 13349415823254323512107320481.3495396037261649201426994438803767191136434970492309775123879)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -300542621510568204264185787475.230003734889859348050696493467253861933279360152095861484548)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 3273919938390136737194044982676.40271056035622723775417608127544182097346526115858803376474)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -22989594065095806099337396006399.5874206181563663855129141706748733174902067950115092492439)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 116970582893952893160414263796102.542775878583510989850142808618916073286745084692189044738)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -459561969036479455224850813196807.283291532483532558959779434457349912822256480548436066098)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1450959909778264914956547227964788.89797179379520834974601372820249784303794436366366810477)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -3782846865486775046285288437885921.41537699732805465141128848354901016102326190612528503251)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 8305043213936355459145388670886540.09976337905520168067329932809302445437208115570138102767)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -15580988484396722546934484726970745.4927787160273626078250810989811865283255762028143642311)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 25262722284076250779006793435537600.0822901485517345545978818780090308947301031347345640449)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -35714428027687018805443603728757116.5304655170478705341887572982734901197345415291580897698)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 44334726194692443174715432419157343.2294160783772787096321009453791271387235388689346602833)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -48599573547617297831555162417695106.187829304963846482633791012658974681648157963911491985)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 47258466493366798944386359199482189.0753349196625125615316002614813737880755896979754845101)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -40913448215392412059728312039233342.142914753896559359297977982314043378636755884088383226)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 31626312914486892948769164616982902.7262756989418188077611392594232674722318027323102462687)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -21878079174441332123064991795834438.4699982361692990285700077902601657354101259411789722708)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 13567268503974326527361474986354265.3136632133935430378937191911532112778452274286122946396)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -7551494211746723529747611556474669.62996644923557605747803028485900789337467673523741066527)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 3775516572689476384052312341432597.70584966904950490541958869730702790312581801585742038997)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -1696271471453637244930364711513292.79902955514107737992185368006225264329876265486853482449)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 684857608019352767999083000986166.20765273693720041519286231015176745354062413008561259139)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -248397566275708464679881624417990.410438107634139924805871051723444048539177890346227250473)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 80880368999557992138783568858556.1512378233079327986518410244522800950609595592170022878937)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -23618197945394013802495450485616.9025005749893350650829964098117490779655546610665927669729)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 6176884636893816103087134481332.06708966653493024119556843727320635285468825056891248447124)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -1444348683723439589948246285262.64080678953468490544615312565485170860503207005915261691108)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 301342031656979076702313946827.961658905182634508217626783081241074250132289461989777865387)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -55959656587719766738301589651.3940625826610668990368881615587469329021742236397809951765678)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 9223339169004064297247180402.36227016155682738556103138196079389248843082157924368301293963)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -1344882881571942601385730283.42710150182526891377514071881534880944872423492272147871101373)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 172841913316760599352601139.54409257740173055624405575900164401527761357324625574736896079)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -19496120443876233531343952.3802212016691702737346568192063937387825469602063310488794471653)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1920907372583710284097959.44121420322495784420169085871802458519363819782779653621724219067)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -164429314798240461613359.399597503536657962383155875723527581699785846599051112719962464604)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 12154026644351189572525.1452249886865981747374191977801688548318519692423556934568426042152)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -770443988366210815096.519382051977221101156336663806705367929328924137169970381042234329058)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 41558909851418707920.4696085656889424895313728719601503526476333404973280596225722152966128)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -1890879946549708819.24562220042687554209318172044783707920086716716717574156283898330017796)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 71844996557297623.9583461685535340440524052492427928388171299145330229958643439878608673403)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -2253785109518255.55600197759875781765803818232939130127735487613049577235879610065545755637)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 57616883849355.997562563968344493719962252675875692642406455612671495250543228005045106721)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -1182495730353.08218118278997948852215670614084013289033222774171548915344541249351599628436)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 19148649358.6196967288062261380599423925174178776792840639099120170800869284300966978300613)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -239779605.891370259668403359614360511661030470269478602533200704639655585967442891496784613)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 2267583.00284368310957842936892685032434505866445291643236133553754152047677944820353796872)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -15749.490806784673108773558070497383604733010677027764233749920147549999361110299643477893)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 77.7059495149052727171505425584459982871343274332635726864135949842508025564999785370162956)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.261619987273930331397625130282851629108569607193781378836014468617185550622160348688297247)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.000572252321659691600529444769356185993188551770817110673186068921175991328434642504616377475)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.765167220661540041663007112207436426423746402583423562585653954743978584117929356523307954e-6)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.579179571056209077507916813937971472839851499147582627425979879366849876944438724610663401e-9)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.224804733043915149719206760378355636826808754704148660354494460792713189958510735070096991e-12)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.392711975389579343321746945135488409914483448652884894759297584020979857734289645857714768e-16)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.258603588346412049542768766878162221817684639789901440429511261589010049357907537684380983e-20)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.499992460848751668441190360024540741752242879565548017176883304716370989218399797418478685e-25)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.196211614533318174187346267877390498735734213905206562766348625767919122511096089367364025e-30)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.874722648949676363732094858062907290148733370978226751462386623191111439121706262759209573e-37)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.163907874717737848669759890242660846846105433791283903651924563157080252845636658802930428e-44)),
};
T result = d[0];
for(unsigned k = 1; k < sizeof(d)/sizeof(d[0]); ++k)
{
result += d[k]/(z+(k-1));
}
return result;
}
template <class T>
static T lanczos_sum_expG_scaled(const T& z)
{
lanczos_initializer<lanczos61UDT, T>::force_instantiate(); // Ensure our constants get initialized before main()
using namespace boost;
static const T d[61] = {
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.901751806425638853077358552989167785490911341809902155556127108480303870921448984935411583e-27)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 4.80241125306810017699523302110401965428995345115391817406006361151407344955277298373661032)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -108.119283021710869401330097315436214587270846871451487282117128515476478251641970487922552)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1177.78262074811362219818923738088833932279000985161077740440010901595132448469513438139561)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -8270.43570321334374279057432173814835581983913167617217749736484999327758232081395983082867)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 42079.807161997077661752306902088979258826568702655699995911391774839958572703348502730394)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -165326.003834443330215001219988296482004968548294447320869281647211603153902436231468280089)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 521978.361504895300685499370463597042533432134369277742485307843747923127933979566742421213)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -1360867.51629992863544553419296636395576666570468519805449755596254912681418267100657262281)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 2987713.73338656161102517003716335104823650191612448011720936412226357385029800040631754755)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -5605212.64915921452169919008770165304171481697939254152852673009005154549681704553438450709)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 9088186.58332916818449459635132673652700922052988327069535513580836143146727832380184335474)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -12848155.5543636394746355365819800465364996596310467415907815393346205151090486190421959769)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 15949281.2867656960575878805158849857756293807220033618942867694361569866468996967761600898)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -17483546.9948295433308250581770557182576171673272450149400973735206019559576269174369907171)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 17001087.8599749419660906448951424280111036786456594738278573653160553115681287326064596964)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -14718487.0643665950346574802384331125115747311674609017568623694516187494204567579595827859)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 11377468.7255609717716845971105161298889777425898291183866813269222281486121330837791392732)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -7870571.64253038587947746661946939286858490057774448573157856145556080330153403858747655263)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 4880783.08440908743641723492059912671377140680710345996273343885045364205895751515063844239)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -2716626.7992639625103140035635916455652302249897918893040695025407382316653674141983775542)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1358230.46602865696544327299659410214201327791319846880787515156343361311278133805428800255)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -610228.440751458395860905749312275043435828322076830117123636938979942213530882048883969802)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 246375.416501158654327780901087115642493055617468601787093268312234390446439555559050129729)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -89360.2599028475206119333931211015869139511677735549267100272095432140508089207221096740632)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 29096.4637987498328341260960356772198979319790332957125131055960448759586930781530063775634)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -8496.57401431514433694413130585404918350686834939156759654375188338156288564260152505382438)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 2222.11523574301594407443285016240908726891841242444092960094015874546135316534057865883047)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -519.599993280949289705514822058693289933461756514489674453254304308040888101533569480646682)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 108.406868361306987817730701109400305482972790224573776407166683184990131682003417239181112)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -20.1313142142558596796857948064047373605439974799116521459977609253211918146595346493447238)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 3.31806787671783168020012913552384112429614503798293169239082032849759155847394955909684383)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.483817477111537877685595212919784447924875428848331771524426361483392903320495411973587861)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.0621793463102927384924303843912913542297042029136293808338022462765755471002366206711862637)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.00701366932085103924241526535768453911099671087892444015581511551813219720807206445462785293)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.000691040514756294308758606917671220770856269030526647010461217455799229645004351524024364997)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.591529398871361458428147660822525365922497109038495896497692806150033516658042357799869656e-4)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.437237367535177689875119370170434437030440227275583289093139147244747901678407875809020739e-5)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.277164853397051135996651958345647824709602266382721185838782221179129726200661453504250697e-6)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.149506899012035980148891401548317536032574502641368034781671941165064546410613201579653674e-7)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.68023824066463262779882895193964639544061678698791279217407325790147925675797085217462974e-9)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.258460163734186329938721529982859244969655253624066115559707985878606277800329299821882688e-10)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.810792256024669306744649981276512583535251727474303382740940985102669076169168931092026491e-12)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.207274966207031327521921078048021807442500113231320959236850963529304158700096495799022922e-13)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.425399199286327802950259994834798737777721414442095221716122926637623478450472871269742436e-15)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.688866766744198529064607574117697940084548375790020728788313274612845280173338912495478431e-17)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.862599751805643281578607291655858333628582704771553874199104377131082877406179933909898885e-19)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.815756005678735657200275584442908437977926312650210429668619446123450972547018343768177988e-21)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.566583084099007858124915716926967268295318152203932871370429534546567151650626184750291695e-23)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.279544761599725082805446124351997692260093135930731230328454667675190245860598623539891708e-25)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.941169851584987983984201821679114408126982142904386301937192011680047611188837432096199601e-28)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.205866011331040736302780507155525142187875191518455173304638008169488993406425201915370746e-30)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.27526655245712584371295491216289353976964567057707464008951584303679019796521332324352501e-33)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.208358067979444305082929004102609366169534624348056112144990933897581971394396210379638792e-36)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.808728107661779323263133007119729988596844663194254976820030366188579170595441991680169012e-40)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.141276924383478964519776436955079978012672985961918248012931336621229652792338950573694356e-43)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.930318449287651389310440021745842417218125582685428432576258687100661462527604238849332053e-48)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.179870748819321661641184169834635133045197146966203370650788171790610563029431722308057539e-52)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.705865243912790337263229413370018392321238639017433365017168104310561824133229343750737083e-58)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.3146787805734405996448268100558028857930560442377698646099945108125281507396722995748398e-64)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.589653534231618730406843260601322236697428143603814281282790370329151249078338470962782338e-72)),
};
T result = d[0];
for(unsigned k = 1; k < sizeof(d)/sizeof(d[0]); ++k)
{
result += d[k]/(z+(k-1));
}
return result;
}
template<class T>
static T lanczos_sum_near_1(const T& dz)
{
lanczos_initializer<lanczos61UDT, T>::force_instantiate(); // Ensure our constants get initialized before main()
using namespace boost;
static const T d[60] = {
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 23.2463658527729692390378860713647146932236940604550445351214987229819352880524561852919518)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -523.358012551815715084547614110229469295755088686612838322817729744722233637819564673967396)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 5701.12892340421080714956066268650092612647620400476183901625272640935853188559347587495571)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -40033.5506451901904954336453419007623117537868026994808919201793803506999271787018654246699)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 203689.884259074923009439144410340256983393397995558814367995938668111650624499963153485034)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -800270.648969745331278757692597096167418585957703057412758177038340791380011708874081291202)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 2526668.23380061659863999395867315313385499515711742092815402701950519696944982260718031476)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -6587362.57559198722630391278043503867973853468105110382293763174847657538179665571836023631)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 14462211.3454541602975917764900442754186801975533106565506542322063393991552960595701762805)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -27132375.1879227404375395522940895789625516798992585980380939378508607160857820002128106898)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 43991923.8735251977856804364757478459275087361742168436524951824945035673768875988985478116)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -62192284.0030124679010201921841372967696262036115679150017649233887633598058364494608060812)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 77203473.0770033513405070667417251568915937590689150831268228886281254637715669678358204991)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -84630180.2217173903516348977915150565994784278120192219937728967986198118628659866582594874)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 82294807.2253549409847505891112074804416229757832871133388349982640444405470371147991706317)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -71245738.2484649177928765605893043553453557808557887270209768163561363857395639001251515788)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 55073334.3180266913441333534260714059077572215147571872597651029894142803987981342430068594)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -38097984.1648990787690036742690550656061009857688125101191167768314179751258568264424911474)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 23625729.5032184580395130592017474282828236643586203914515183078852982915252442161768527976)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -13149998.4348054726172055622442157883429575511528431835657668083088902165366619827169829685)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 6574597.77221556423683199818131482663205682902023554728024972161230111356285973623550338976)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -2953848.1483469149918109110050192571921018042012905892107136410603990336401921230407043408)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1192595.29584357246380113611351829515963605337523874715861849584306265512819543347806085356)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -432553.812019608638388918135375154289816441900572658692369491476137741687213006403648722272)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 140843.215385933866391177743292449477205328233960902455943995092958295858485718885800427129)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -41128.186992679630058614841985110676526199977321524879849001760603476646382839182691529968)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 10756.2849191854701631989789887757784944313743544315113894758328432005767448056040879337769)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -2515.15559672041299884426826962296210458052543246529646213159169885444118227871246315458787)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 524.750087004805200600237632074908875763734578390662349666321453103782638818305404274166951)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -97.4468596421732493988298219295878130651986131393383646674144877163795143930682205035917965)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 16.0613108128210806736384551896802799172445298357754547684100294231532127326987175444453058)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -2.34194813526540240672426202485306862230641838409943369059203455578340880900483887447559874)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.300982934748016059399829007219431333744032924923669397318820178988611410275964499475465815)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.033950095985367909789000959795708551814461844488183964432565731809399824963680858993718525)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.00334502394288921146242772614150438404658527112198421937945605441697314216921393987758378122)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.000286333429067523984607730553301991502191011265745476190940771685897687956262049750683013485)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.211647426149364947402896718485536530479491688838087899435991994237067890628274492042231115e-4)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.134163345121302758109675190598169832775248626443483098532368562186356128620805552609175683e-5)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.723697303042715085329782938306424498336642078597508935450663080894255773653328980495047891e-7)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.329273487343139063533251321553223583999676337945788660475231347828772272134656322947906888e-8)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.12510922551028971731767784013117088894558604838820475961392154031378891971216135267744134e-9)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.392468958215589939603666430583400537413757786057185505426804034745840192914621891690369903e-11)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.100332717101049934370760667782927946803279422001380028508200697081188326364078428184546051e-12)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.205917088291197705194762747639836655808855850989058813560983717575008725393428497910009756e-14)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.333450178247893143608439314203175490705783992567107481617660357577257627854979230819461489e-16)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.417546693906616047110563550428133589051498362676394888715581845170969319500638944065594319e-18)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.394871691642184410859178529844325390739857256666676534513661579365702353214518478078730801e-20)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.274258012587811199757875927548699264063511843669070634471054184977334027224611843434000922e-22)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.135315354265459854889496635967343027244391821142592599244505313738163473730636430399785048e-24)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.455579032003288910408487905303223613382276173706542364543918076752861628464036586507967767e-27)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.99650703862462739161520123768147312466695159780582506041370833824093136783202694548427718e-30)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.1332444609228706921659395801935919548447859029572115502899861345555006827214220195650058e-32)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.100856999148765307000182397631280249632761913433008379786888200467467364474581430670889392e-35)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.39146979455613683472384690509165395074425354524713697428673406058157887065953366609738731e-39)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.683859606707931248105140296850112494069265272540298100341919970496564103098283709868586478e-43)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.450326344248604222735147147805963966503893913752040066400766411031387063854141246972061792e-47)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.870675378039492904184581895322153006461319724931909799151743284769901586333730037761678891e-52)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.341678395249272265744518787745356400350877656459401143889000625280131819505857966769964401e-57)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.152322191370871666358069530949353871960316638394428595988162174042653299702098929238880862e-63)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.285425405297633795767452984791738825078111150078605004958179057245980222485147999495352632e-71)),
};
T result = 0;
for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k)
{
result += (-d[k-1]*dz)/(k*dz + k*k);
}
return result;
}
template<class T>
static T lanczos_sum_near_2(const T& dz)
{
lanczos_initializer<lanczos61UDT, T>::force_instantiate(); // Ensure our constants get initialized before main()
using namespace boost;
static const T d[60] = {
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 557.56438192770795764344217888434355281097193198928944200046501607026919782564033547346298)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -12552.748616427645475141433405567201788681683808077269330800392600825597799119572762385222)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 136741.650054039199076788077149441364242294724343897779563222338447737802381279007988884806)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -960205.223613240309942047656967301131022760634321049075674684679438471862998829007639437133)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 4885504.47588736223774859617054275229642041717942140469884121916073195308537421162982679289)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -19194501.738192166918904824982935279260356575935661514109550613809352009246483412530545583)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 60602169.8633537742937457094837494059849674261357199218329545854990149896822944801504450843)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -157997975.522506767297528502540724511908584668874487506510120462561270100749019845014382885)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 346876323.86092543685419723290495817330608574729543216092477261152247521712190505658568876)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -650770365.471136883718747607976242475416651908858429752332176373467422603953536408709972919)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1055146856.05909309330903130910708372830487315684258450293308627289334336871273080305128138)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -1491682726.25614447429071368736790697283307005456720192465860871846879804207692411263924608)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1851726287.94866167094858600116562210167031458934987154557042242638980748286188183300900268)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -2029855953.68334371445800569238095379629407314338521720558391277508374519526853827142679839)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1973842002.53354868177824629525448788555435194808657489238517523691040148611221295436287925)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -1708829941.98209573247426625323314413060108441455314880934710595647408841619484540679859098)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 1320934627.12433688699625456833930317624783222321555050330381730035733198249283009357314954)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -913780636.858542526294419197161614811332299249415125108737474024007693329922089123296358727)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 566663423.929632170286007468016419798879660054391183200464733820209439185545886930103546787)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -315402880.436816230388857961460509181823167373029384218959199936902955049832392362044305869)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 157691811.550465734461741500275930418786875005567018699867961482249002625886064187146134966)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -70848085.5705405970640618473551954585013808128304384354476488268600720054598122945113512731)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 28604413.4050137708444142264980840059788755325900041515286382001704951527733220637586013815)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -10374808.7067303054787164054055989420809074792801592763124972441820101840292558840131568633)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 3378126.32016207486657791623723515804931231041318964254116390764473281291389374196880720069)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -986460.090390653140964189383080344920103075349535669020623874668558777188889544398718979744)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 257989.631187387317948158483575125380011593209850756066176921901006833159795100137743395985)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -60326.0391159227288325790327830741260824763549807922845004854215660451399733578621565837087)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 12586.1375399649496159880821645216260841794563919652590583420570326276086323953958907053394)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -2337.26417330316922535871922886167444795452055677161063205953141105726549966801856628447293)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 385.230745012608736644117458716226876976056390433401632749144285378123105481506733917763829)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -56.1716559403731491675970177460841997333796694857076749852739159067307309470690838101179615)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 7.21907953468550196348585224042498727840087634483369357697580053424523903859773769748599575)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.814293485887386870805786409956942772883474224091975496298369877683530509729332902182019049)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.0802304419995150047616460464220884371214157889148846405799324851793571580868840034085001373)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.00686771095380619535195996193943858680694970000948742557733102777115482017857981277171196115)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.000507636621977556438232617777542864427109623356049335590894564220687567763620803789858345916)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.32179095465362720747836116655088181481893063531138957363431280817392443948706754917605911e-4)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.173578890579848508947329833426585354230744194615295570820295052665075101971588563893718407e-5)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.789762880006288893888161070734302768702358633525134582027140158619195373770299678322596835e-7)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.300074637200885066788470310738617992259402710843493097610337134266720909870967550606601658e-8)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.941337297619721713151110244242536308266701344868601679868536153775533330272973088246835359e-10)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.24064815013182536657310186836079333949814111498828401548170442715552017773994482539471456e-11)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.493892399304811910466345686492277504628763169549384435563232052965821874553923373100791477e-13)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.799780678476644196901221989475355609743387528732994566453160178199295104357319723742820593e-15)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.100148627870893347527249092785257443532967736956154251497569191947184705954310833302770086e-16)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.947100256812658897084619699699028861352615460106539259289295071616221848196411749449858071e-19)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.657808193528898116367845405906343884364280888644748907819280236995018351085371701094007759e-21)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.324554050057463845012469010247790763753999056976705084126950591088538742509983426730851614e-23)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.10927068902162908990029309141242256163212535730975970310918370355165185052827948996110107e-25)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.239012340507870646690121104637467232366271566488184795459093215303237974655782634371712486e-28)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.31958700972990573259359660326375143524864710953063781494908314884519046349402409667329667e-31)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.241905641292988284384362036555782113275737930713192053073501265726048089991747342247551645e-34)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.93894080230619233745797029179332447129464915420290457418429337322820997038069119047864035e-38)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.164023814025085488413251990798690797467351995518990067783355251949198292596815470576539877e-41)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.108010831192689925518484618970761942019888832176355541674171850211917230280206410356465451e-45)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.208831600642796805563854019033577205240227465154130766898180386564934443551840379116390645e-50)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.819516067465171848863933747691434138146789031214932473898084756489529673230665363014007306e-56)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, 0.365344970579318347488211604761724311582675708113250505307342682118101409913523622073678179e-62)),
static_cast<T>(BOOST_MATH_HUGE_CONSTANT(T, 150, -0.684593199208628857931267904308244537968349564351534581234005234847904343404822808648361291e-70)),
};
T result = 0;
T z = dz + 2;
for(unsigned k = 1; k <= sizeof(d)/sizeof(d[0]); ++k)
{
result += (-d[k-1]*dz)/(z + k*z + k*k - 1);
}
return result;
}
static double g(){ return 63.19215200000000010049916454590857028961181640625; }
};
}}} // namespaces
#endif

View File

@@ -0,0 +1,809 @@
// Copyright John Maddock 2008.
// 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)
//
// Wrapper that works with mpfr_class defined in gmpfrxx.h
// See http://math.berkeley.edu/~wilken/code/gmpfrxx/
// Also requires the gmp and mpfr libraries.
//
#ifndef BOOST_MATH_E_FLOAT_BINDINGS_HPP
#define BOOST_MATH_E_FLOAT_BINDINGS_HPP
#include <boost/config.hpp>
#include <e_float/e_float.h>
#include <functions/functions.h>
#include <boost/math/tools/precision.hpp>
#include <boost/math/tools/real_cast.hpp>
#include <boost/math/policies/policy.hpp>
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/bindings/detail/big_digamma.hpp>
#include <boost/math/bindings/detail/big_lanczos.hpp>
#include <boost/lexical_cast.hpp>
namespace boost{ namespace math{ namespace ef{
class e_float
{
public:
// Constructors:
e_float() {}
e_float(const ::e_float& c) : m_value(c){}
e_float(char c)
{
m_value = ::e_float(c);
}
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
e_float(wchar_t c)
{
m_value = ::e_float(c);
}
#endif
e_float(unsigned char c)
{
m_value = ::e_float(c);
}
e_float(signed char c)
{
m_value = ::e_float(c);
}
e_float(unsigned short c)
{
m_value = ::e_float(c);
}
e_float(short c)
{
m_value = ::e_float(c);
}
e_float(unsigned int c)
{
m_value = ::e_float(c);
}
e_float(int c)
{
m_value = ::e_float(c);
}
e_float(unsigned long c)
{
m_value = ::e_float((UINT64)c);
}
e_float(long c)
{
m_value = ::e_float((INT64)c);
}
#ifdef BOOST_HAS_LONG_LONG
e_float(boost::ulong_long_type c)
{
m_value = ::e_float(c);
}
e_float(boost::long_long_type c)
{
m_value = ::e_float(c);
}
#endif
e_float(float c)
{
assign_large_real(c);
}
e_float(double c)
{
assign_large_real(c);
}
e_float(long double c)
{
assign_large_real(c);
}
// Assignment:
e_float& operator=(char c) { m_value = ::e_float(c); return *this; }
e_float& operator=(unsigned char c) { m_value = ::e_float(c); return *this; }
e_float& operator=(signed char c) { m_value = ::e_float(c); return *this; }
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
e_float& operator=(wchar_t c) { m_value = ::e_float(c); return *this; }
#endif
e_float& operator=(short c) { m_value = ::e_float(c); return *this; }
e_float& operator=(unsigned short c) { m_value = ::e_float(c); return *this; }
e_float& operator=(int c) { m_value = ::e_float(c); return *this; }
e_float& operator=(unsigned int c) { m_value = ::e_float(c); return *this; }
e_float& operator=(long c) { m_value = ::e_float((INT64)c); return *this; }
e_float& operator=(unsigned long c) { m_value = ::e_float((UINT64)c); return *this; }
#ifdef BOOST_HAS_LONG_LONG
e_float& operator=(boost::long_long_type c) { m_value = ::e_float(c); return *this; }
e_float& operator=(boost::ulong_long_type c) { m_value = ::e_float(c); return *this; }
#endif
e_float& operator=(float c) { assign_large_real(c); return *this; }
e_float& operator=(double c) { assign_large_real(c); return *this; }
e_float& operator=(long double c) { assign_large_real(c); return *this; }
// Access:
::e_float& value(){ return m_value; }
::e_float const& value()const{ return m_value; }
// Member arithmetic:
e_float& operator+=(const e_float& other)
{ m_value += other.value(); return *this; }
e_float& operator-=(const e_float& other)
{ m_value -= other.value(); return *this; }
e_float& operator*=(const e_float& other)
{ m_value *= other.value(); return *this; }
e_float& operator/=(const e_float& other)
{ m_value /= other.value(); return *this; }
e_float operator-()const
{ return -m_value; }
e_float const& operator+()const
{ return *this; }
private:
::e_float m_value;
template <class V>
void assign_large_real(const V& a)
{
using std::frexp;
using std::ldexp;
using std::floor;
if (a == 0) {
m_value = ::ef::zero();
return;
}
if (a == 1) {
m_value = ::ef::one();
return;
}
if ((boost::math::isinf)(a))
{
m_value = a > 0 ? m_value.my_value_inf() : -m_value.my_value_inf();
return;
}
if((boost::math::isnan)(a))
{
m_value = m_value.my_value_nan();
return;
}
int e;
long double f, term;
::e_float t;
m_value = ::ef::zero();
f = frexp(a, &e);
::e_float shift = ::ef::pow2(30);
while(f)
{
// extract 30 bits from f:
f = ldexp(f, 30);
term = floor(f);
e -= 30;
m_value *= shift;
m_value += ::e_float(static_cast<INT64>(term));
f -= term;
}
m_value *= ::ef::pow2(e);
}
};
// Non-member arithmetic:
inline e_float operator+(const e_float& a, const e_float& b)
{
e_float result(a);
result += b;
return result;
}
inline e_float operator-(const e_float& a, const e_float& b)
{
e_float result(a);
result -= b;
return result;
}
inline e_float operator*(const e_float& a, const e_float& b)
{
e_float result(a);
result *= b;
return result;
}
inline e_float operator/(const e_float& a, const e_float& b)
{
e_float result(a);
result /= b;
return result;
}
// Comparison:
inline bool operator == (const e_float& a, const e_float& b)
{ return a.value() == b.value() ? true : false; }
inline bool operator != (const e_float& a, const e_float& b)
{ return a.value() != b.value() ? true : false;}
inline bool operator < (const e_float& a, const e_float& b)
{ return a.value() < b.value() ? true : false; }
inline bool operator <= (const e_float& a, const e_float& b)
{ return a.value() <= b.value() ? true : false; }
inline bool operator > (const e_float& a, const e_float& b)
{ return a.value() > b.value() ? true : false; }
inline bool operator >= (const e_float& a, const e_float& b)
{ return a.value() >= b.value() ? true : false; }
std::istream& operator >> (std::istream& is, e_float& f)
{
return is >> f.value();
}
std::ostream& operator << (std::ostream& os, const e_float& f)
{
return os << f.value();
}
inline e_float fabs(const e_float& v)
{
return ::ef::fabs(v.value());
}
inline e_float abs(const e_float& v)
{
return ::ef::fabs(v.value());
}
inline e_float floor(const e_float& v)
{
return ::ef::floor(v.value());
}
inline e_float ceil(const e_float& v)
{
return ::ef::ceil(v.value());
}
inline e_float pow(const e_float& v, const e_float& w)
{
return ::ef::pow(v.value(), w.value());
}
inline e_float pow(const e_float& v, int i)
{
return ::ef::pow(v.value(), ::e_float(i));
}
inline e_float exp(const e_float& v)
{
return ::ef::exp(v.value());
}
inline e_float log(const e_float& v)
{
return ::ef::log(v.value());
}
inline e_float sqrt(const e_float& v)
{
return ::ef::sqrt(v.value());
}
inline e_float sin(const e_float& v)
{
return ::ef::sin(v.value());
}
inline e_float cos(const e_float& v)
{
return ::ef::cos(v.value());
}
inline e_float tan(const e_float& v)
{
return ::ef::tan(v.value());
}
inline e_float acos(const e_float& v)
{
return ::ef::acos(v.value());
}
inline e_float asin(const e_float& v)
{
return ::ef::asin(v.value());
}
inline e_float atan(const e_float& v)
{
return ::ef::atan(v.value());
}
inline e_float atan2(const e_float& v, const e_float& u)
{
return ::ef::atan2(v.value(), u.value());
}
inline e_float ldexp(const e_float& v, int e)
{
return v.value() * ::ef::pow2(e);
}
inline e_float frexp(const e_float& v, int* expon)
{
double d;
INT64 i;
v.value().extract_parts(d, i);
*expon = static_cast<int>(i);
return v.value() * ::ef::pow2(-i);
}
inline e_float sinh (const e_float& x)
{
return ::ef::sinh(x.value());
}
inline e_float cosh (const e_float& x)
{
return ::ef::cosh(x.value());
}
inline e_float tanh (const e_float& x)
{
return ::ef::tanh(x.value());
}
inline e_float asinh (const e_float& x)
{
return ::ef::asinh(x.value());
}
inline e_float acosh (const e_float& x)
{
return ::ef::acosh(x.value());
}
inline e_float atanh (const e_float& x)
{
return ::ef::atanh(x.value());
}
e_float fmod(const e_float& v1, const e_float& v2)
{
e_float n;
if(v1 < 0)
n = ceil(v1 / v2);
else
n = floor(v1 / v2);
return v1 - n * v2;
}
} namespace detail{
template <>
inline int fpclassify_imp< boost::math::ef::e_float> BOOST_NO_MACRO_EXPAND(boost::math::ef::e_float x, const generic_tag<true>&)
{
if(x.value().isnan())
return FP_NAN;
if(x.value().isinf())
return FP_INFINITE;
if(x == 0)
return FP_ZERO;
return FP_NORMAL;
}
} namespace ef{
template <class Policy>
inline int itrunc(const e_float& v, const Policy& pol)
{
BOOST_MATH_STD_USING
e_float r = boost::math::trunc(v, pol);
if(fabs(r) > (std::numeric_limits<int>::max)())
return static_cast<int>(policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", 0, 0, v, pol));
return static_cast<int>(r.value().extract_int64());
}
template <class Policy>
inline long ltrunc(const e_float& v, const Policy& pol)
{
BOOST_MATH_STD_USING
e_float r = boost::math::trunc(v, pol);
if(fabs(r) > (std::numeric_limits<long>::max)())
return static_cast<long>(policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", 0, 0L, v, pol));
return static_cast<long>(r.value().extract_int64());
}
#ifdef BOOST_HAS_LONG_LONG
template <class Policy>
inline boost::long_long_type lltrunc(const e_float& v, const Policy& pol)
{
BOOST_MATH_STD_USING
e_float r = boost::math::trunc(v, pol);
if(fabs(r) > (std::numeric_limits<boost::long_long_type>::max)())
return static_cast<boost::long_long_type>(policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", 0, v, 0LL, pol).value().extract_int64());
return static_cast<boost::long_long_type>(r.value().extract_int64());
}
#endif
template <class Policy>
inline int iround(const e_float& v, const Policy& pol)
{
BOOST_MATH_STD_USING
e_float r = boost::math::round(v, pol);
if(fabs(r) > (std::numeric_limits<int>::max)())
return static_cast<int>(policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", 0, v, 0, pol).value().extract_int64());
return static_cast<int>(r.value().extract_int64());
}
template <class Policy>
inline long lround(const e_float& v, const Policy& pol)
{
BOOST_MATH_STD_USING
e_float r = boost::math::round(v, pol);
if(fabs(r) > (std::numeric_limits<long>::max)())
return static_cast<long int>(policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", 0, v, 0L, pol).value().extract_int64());
return static_cast<long int>(r.value().extract_int64());
}
#ifdef BOOST_HAS_LONG_LONG
template <class Policy>
inline boost::long_long_type llround(const e_float& v, const Policy& pol)
{
BOOST_MATH_STD_USING
e_float r = boost::math::round(v, pol);
if(fabs(r) > (std::numeric_limits<boost::long_long_type>::max)())
return static_cast<boost::long_long_type>(policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", 0, v, 0LL, pol).value().extract_int64());
return static_cast<boost::long_long_type>(r.value().extract_int64());
}
#endif
}}}
namespace std{
template<>
class numeric_limits< ::boost::math::ef::e_float> : public numeric_limits< ::e_float>
{
public:
static const ::boost::math::ef::e_float (min) (void)
{
return (numeric_limits< ::e_float>::min)();
}
static const ::boost::math::ef::e_float (max) (void)
{
return (numeric_limits< ::e_float>::max)();
}
static const ::boost::math::ef::e_float epsilon (void)
{
return (numeric_limits< ::e_float>::epsilon)();
}
static const ::boost::math::ef::e_float round_error(void)
{
return (numeric_limits< ::e_float>::round_error)();
}
static const ::boost::math::ef::e_float infinity (void)
{
return (numeric_limits< ::e_float>::infinity)();
}
static const ::boost::math::ef::e_float quiet_NaN (void)
{
return (numeric_limits< ::e_float>::quiet_NaN)();
}
//
// e_float's supplied digits member is wrong
// - it should be same the same as digits 10
// - given that radix is 10.
//
static const int digits = digits10;
};
} // namespace std
namespace boost{ namespace math{
namespace policies{
template <class Policy>
struct precision< ::boost::math::ef::e_float, Policy>
{
typedef typename Policy::precision_type precision_type;
typedef digits2<((::std::numeric_limits< ::boost::math::ef::e_float>::digits10 + 1) * 1000L) / 301L> digits_2;
typedef typename mpl::if_c<
((digits_2::value <= precision_type::value)
|| (Policy::precision_type::value <= 0)),
// Default case, full precision for RealType:
digits_2,
// User customised precision:
precision_type
>::type type;
};
}
namespace tools{
template <>
inline int digits< ::boost::math::ef::e_float>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC( ::boost::math::ef::e_float))
{
return ((::std::numeric_limits< ::boost::math::ef::e_float>::digits10 + 1) * 1000L) / 301L;
}
template <>
inline ::boost::math::ef::e_float root_epsilon< ::boost::math::ef::e_float>()
{
return detail::root_epsilon_imp(static_cast< ::boost::math::ef::e_float const*>(0), mpl::int_<0>());
}
template <>
inline ::boost::math::ef::e_float forth_root_epsilon< ::boost::math::ef::e_float>()
{
return detail::forth_root_epsilon_imp(static_cast< ::boost::math::ef::e_float const*>(0), mpl::int_<0>());
}
}
namespace lanczos{
template<class Policy>
struct lanczos<boost::math::ef::e_float, Policy>
{
typedef typename mpl::if_c<
std::numeric_limits< ::e_float>::digits10 < 22,
lanczos13UDT,
typename mpl::if_c<
std::numeric_limits< ::e_float>::digits10 < 36,
lanczos22UDT,
typename mpl::if_c<
std::numeric_limits< ::e_float>::digits10 < 50,
lanczos31UDT,
typename mpl::if_c<
std::numeric_limits< ::e_float>::digits10 < 110,
lanczos61UDT,
undefined_lanczos
>::type
>::type
>::type
>::type type;
};
} // namespace lanczos
template <class Policy>
inline boost::math::ef::e_float skewness(const extreme_value_distribution<boost::math::ef::e_float, Policy>& /*dist*/)
{
//
// This is 12 * sqrt(6) * zeta(3) / pi^3:
// See http://mathworld.wolfram.com/ExtremeValueDistribution.html
//
return boost::lexical_cast<boost::math::ef::e_float>("1.1395470994046486574927930193898461120875997958366");
}
template <class Policy>
inline boost::math::ef::e_float skewness(const rayleigh_distribution<boost::math::ef::e_float, Policy>& /*dist*/)
{
// using namespace boost::math::constants;
return boost::lexical_cast<boost::math::ef::e_float>("0.63111065781893713819189935154422777984404221106391");
// 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 Policy>
inline boost::math::ef::e_float kurtosis(const rayleigh_distribution<boost::math::ef::e_float, Policy>& /*dist*/)
{
// using namespace boost::math::constants;
return boost::lexical_cast<boost::math::ef::e_float>("3.2450893006876380628486604106197544154170667057995");
// 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 Policy>
inline boost::math::ef::e_float kurtosis_excess(const rayleigh_distribution<boost::math::ef::e_float, Policy>& /*dist*/)
{
//using namespace boost::math::constants;
// Computed using NTL at 150 bit, about 50 decimal digits.
return boost::lexical_cast<boost::math::ef::e_float>("0.2450893006876380628486604106197544154170667057995");
// return -(6 * pi<RealType>() * pi<RealType>() - 24 * pi<RealType>() + 16) /
// (four_minus_pi<RealType>() * four_minus_pi<RealType>());
} // kurtosis
namespace detail{
//
// Version of Digamma accurate to ~100 decimal digits.
//
template <class Policy>
boost::math::ef::e_float digamma_imp(boost::math::ef::e_float x, const mpl::int_<0>* , const Policy& pol)
{
//
// This handles reflection of negative arguments, and all our
// eboost::math::ef::e_floator handling, then forwards to the T-specific approximation.
//
BOOST_MATH_STD_USING // ADL of std functions.
boost::math::ef::e_float result = 0;
//
// Check for negative arguments and use reflection:
//
if(x < 0)
{
// Reflect:
x = 1 - x;
// Argument reduction for tan:
boost::math::ef::e_float remainder = x - floor(x);
// Shift to negative if > 0.5:
if(remainder > 0.5)
{
remainder -= 1;
}
//
// check for evaluation at a negative pole:
//
if(remainder == 0)
{
return policies::raise_pole_error<boost::math::ef::e_float>("boost::math::digamma<%1%>(%1%)", 0, (1-x), pol);
}
result = constants::pi<boost::math::ef::e_float>() / tan(constants::pi<boost::math::ef::e_float>() * remainder);
}
result += big_digamma(x);
return result;
}
boost::math::ef::e_float bessel_i0(boost::math::ef::e_float x)
{
static const boost::math::ef::e_float P1[] = {
boost::lexical_cast<boost::math::ef::e_float>("-2.2335582639474375249e+15"),
boost::lexical_cast<boost::math::ef::e_float>("-5.5050369673018427753e+14"),
boost::lexical_cast<boost::math::ef::e_float>("-3.2940087627407749166e+13"),
boost::lexical_cast<boost::math::ef::e_float>("-8.4925101247114157499e+11"),
boost::lexical_cast<boost::math::ef::e_float>("-1.1912746104985237192e+10"),
boost::lexical_cast<boost::math::ef::e_float>("-1.0313066708737980747e+08"),
boost::lexical_cast<boost::math::ef::e_float>("-5.9545626019847898221e+05"),
boost::lexical_cast<boost::math::ef::e_float>("-2.4125195876041896775e+03"),
boost::lexical_cast<boost::math::ef::e_float>("-7.0935347449210549190e+00"),
boost::lexical_cast<boost::math::ef::e_float>("-1.5453977791786851041e-02"),
boost::lexical_cast<boost::math::ef::e_float>("-2.5172644670688975051e-05"),
boost::lexical_cast<boost::math::ef::e_float>("-3.0517226450451067446e-08"),
boost::lexical_cast<boost::math::ef::e_float>("-2.6843448573468483278e-11"),
boost::lexical_cast<boost::math::ef::e_float>("-1.5982226675653184646e-14"),
boost::lexical_cast<boost::math::ef::e_float>("-5.2487866627945699800e-18"),
};
static const boost::math::ef::e_float Q1[] = {
boost::lexical_cast<boost::math::ef::e_float>("-2.2335582639474375245e+15"),
boost::lexical_cast<boost::math::ef::e_float>("7.8858692566751002988e+12"),
boost::lexical_cast<boost::math::ef::e_float>("-1.2207067397808979846e+10"),
boost::lexical_cast<boost::math::ef::e_float>("1.0377081058062166144e+07"),
boost::lexical_cast<boost::math::ef::e_float>("-4.8527560179962773045e+03"),
boost::lexical_cast<boost::math::ef::e_float>("1.0"),
};
static const boost::math::ef::e_float P2[] = {
boost::lexical_cast<boost::math::ef::e_float>("-2.2210262233306573296e-04"),
boost::lexical_cast<boost::math::ef::e_float>("1.3067392038106924055e-02"),
boost::lexical_cast<boost::math::ef::e_float>("-4.4700805721174453923e-01"),
boost::lexical_cast<boost::math::ef::e_float>("5.5674518371240761397e+00"),
boost::lexical_cast<boost::math::ef::e_float>("-2.3517945679239481621e+01"),
boost::lexical_cast<boost::math::ef::e_float>("3.1611322818701131207e+01"),
boost::lexical_cast<boost::math::ef::e_float>("-9.6090021968656180000e+00"),
};
static const boost::math::ef::e_float Q2[] = {
boost::lexical_cast<boost::math::ef::e_float>("-5.5194330231005480228e-04"),
boost::lexical_cast<boost::math::ef::e_float>("3.2547697594819615062e-02"),
boost::lexical_cast<boost::math::ef::e_float>("-1.1151759188741312645e+00"),
boost::lexical_cast<boost::math::ef::e_float>("1.3982595353892851542e+01"),
boost::lexical_cast<boost::math::ef::e_float>("-6.0228002066743340583e+01"),
boost::lexical_cast<boost::math::ef::e_float>("8.5539563258012929600e+01"),
boost::lexical_cast<boost::math::ef::e_float>("-3.1446690275135491500e+01"),
boost::lexical_cast<boost::math::ef::e_float>("1.0"),
};
boost::math::ef::e_float 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<boost::math::ef::e_float>(1);
}
if (x <= 15) // x in (0, 15]
{
boost::math::ef::e_float y = x * x;
value = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
}
else // x in (15, \infty)
{
boost::math::ef::e_float y = 1 / x - boost::math::ef::e_float(1) / 15;
r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
factor = exp(x) / sqrt(x);
value = factor * r;
}
return value;
}
boost::math::ef::e_float bessel_i1(boost::math::ef::e_float x)
{
static const boost::math::ef::e_float P1[] = {
lexical_cast<boost::math::ef::e_float>("-1.4577180278143463643e+15"),
lexical_cast<boost::math::ef::e_float>("-1.7732037840791591320e+14"),
lexical_cast<boost::math::ef::e_float>("-6.9876779648010090070e+12"),
lexical_cast<boost::math::ef::e_float>("-1.3357437682275493024e+11"),
lexical_cast<boost::math::ef::e_float>("-1.4828267606612366099e+09"),
lexical_cast<boost::math::ef::e_float>("-1.0588550724769347106e+07"),
lexical_cast<boost::math::ef::e_float>("-5.1894091982308017540e+04"),
lexical_cast<boost::math::ef::e_float>("-1.8225946631657315931e+02"),
lexical_cast<boost::math::ef::e_float>("-4.7207090827310162436e-01"),
lexical_cast<boost::math::ef::e_float>("-9.1746443287817501309e-04"),
lexical_cast<boost::math::ef::e_float>("-1.3466829827635152875e-06"),
lexical_cast<boost::math::ef::e_float>("-1.4831904935994647675e-09"),
lexical_cast<boost::math::ef::e_float>("-1.1928788903603238754e-12"),
lexical_cast<boost::math::ef::e_float>("-6.5245515583151902910e-16"),
lexical_cast<boost::math::ef::e_float>("-1.9705291802535139930e-19"),
};
static const boost::math::ef::e_float Q1[] = {
lexical_cast<boost::math::ef::e_float>("-2.9154360556286927285e+15"),
lexical_cast<boost::math::ef::e_float>("9.7887501377547640438e+12"),
lexical_cast<boost::math::ef::e_float>("-1.4386907088588283434e+10"),
lexical_cast<boost::math::ef::e_float>("1.1594225856856884006e+07"),
lexical_cast<boost::math::ef::e_float>("-5.1326864679904189920e+03"),
lexical_cast<boost::math::ef::e_float>("1.0"),
};
static const boost::math::ef::e_float P2[] = {
lexical_cast<boost::math::ef::e_float>("1.4582087408985668208e-05"),
lexical_cast<boost::math::ef::e_float>("-8.9359825138577646443e-04"),
lexical_cast<boost::math::ef::e_float>("2.9204895411257790122e-02"),
lexical_cast<boost::math::ef::e_float>("-3.4198728018058047439e-01"),
lexical_cast<boost::math::ef::e_float>("1.3960118277609544334e+00"),
lexical_cast<boost::math::ef::e_float>("-1.9746376087200685843e+00"),
lexical_cast<boost::math::ef::e_float>("8.5591872901933459000e-01"),
lexical_cast<boost::math::ef::e_float>("-6.0437159056137599999e-02"),
};
static const boost::math::ef::e_float Q2[] = {
lexical_cast<boost::math::ef::e_float>("3.7510433111922824643e-05"),
lexical_cast<boost::math::ef::e_float>("-2.2835624489492512649e-03"),
lexical_cast<boost::math::ef::e_float>("7.4212010813186530069e-02"),
lexical_cast<boost::math::ef::e_float>("-8.5017476463217924408e-01"),
lexical_cast<boost::math::ef::e_float>("3.2593714889036996297e+00"),
lexical_cast<boost::math::ef::e_float>("-3.8806586721556593450e+00"),
lexical_cast<boost::math::ef::e_float>("1.0"),
};
boost::math::ef::e_float value, factor, r, w;
BOOST_MATH_STD_USING
using namespace boost::math::tools;
w = abs(x);
if (x == 0)
{
return static_cast<boost::math::ef::e_float>(0);
}
if (w <= 15) // w in (0, 15]
{
boost::math::ef::e_float y = x * x;
r = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
factor = w;
value = factor * r;
}
else // w in (15, \infty)
{
boost::math::ef::e_float y = 1 / w - boost::math::ef::e_float(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;
}
} // namespace detail
}}
#endif // BOOST_MATH_E_FLOAT_BINDINGS_HPP

View File

@@ -0,0 +1,954 @@
// Copyright John Maddock 2008.
// 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)
//
// Wrapper that works with mpfr_class defined in gmpfrxx.h
// See http://math.berkeley.edu/~wilken/code/gmpfrxx/
// Also requires the gmp and mpfr libraries.
//
#ifndef BOOST_MATH_MPLFR_BINDINGS_HPP
#define BOOST_MATH_MPLFR_BINDINGS_HPP
#include <boost/config.hpp>
#include <boost/lexical_cast.hpp>
#ifdef BOOST_MSVC
//
// We get a lot of warnings from the gmp, mpfr and gmpfrxx headers,
// disable them here, so we only see warnings from *our* code:
//
#pragma warning(push)
#pragma warning(disable: 4127 4800 4512)
#endif
#include <gmpfrxx.h>
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#include <boost/math/tools/precision.hpp>
#include <boost/math/tools/real_cast.hpp>
#include <boost/math/policies/policy.hpp>
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/bindings/detail/big_digamma.hpp>
#include <boost/math/bindings/detail/big_lanczos.hpp>
#include <boost/math/tools/big_constant.hpp>
inline mpfr_class fabs(const mpfr_class& v)
{
return abs(v);
}
template <class T, class U>
inline mpfr_class fabs(const __gmp_expr<T,U>& v)
{
return abs(static_cast<mpfr_class>(v));
}
inline mpfr_class pow(const mpfr_class& b, const mpfr_class& e)
{
mpfr_class result;
mpfr_pow(result.__get_mp(), b.__get_mp(), e.__get_mp(), GMP_RNDN);
return result;
}
/*
template <class T, class U, class V, class W>
inline mpfr_class pow(const __gmp_expr<T,U>& b, const __gmp_expr<V,W>& e)
{
return pow(static_cast<mpfr_class>(b), static_cast<mpfr_class>(e));
}
*/
inline mpfr_class ldexp(const mpfr_class& v, int e)
{
//int e = mpfr_get_exp(*v.__get_mp());
mpfr_class result(v);
mpfr_set_exp(result.__get_mp(), e);
return result;
}
template <class T, class U>
inline mpfr_class ldexp(const __gmp_expr<T,U>& v, int e)
{
return ldexp(static_cast<mpfr_class>(v), e);
}
inline mpfr_class frexp(const mpfr_class& v, int* expon)
{
int e = mpfr_get_exp(v.__get_mp());
mpfr_class result(v);
mpfr_set_exp(result.__get_mp(), 0);
*expon = e;
return result;
}
template <class T, class U>
inline mpfr_class frexp(const __gmp_expr<T,U>& v, int* expon)
{
return frexp(static_cast<mpfr_class>(v), expon);
}
inline mpfr_class fmod(const mpfr_class& v1, const mpfr_class& v2)
{
mpfr_class n;
if(v1 < 0)
n = ceil(v1 / v2);
else
n = floor(v1 / v2);
return v1 - n * v2;
}
template <class T, class U, class V, class W>
inline mpfr_class fmod(const __gmp_expr<T,U>& v1, const __gmp_expr<V,W>& v2)
{
return fmod(static_cast<mpfr_class>(v1), static_cast<mpfr_class>(v2));
}
template <class Policy>
inline mpfr_class modf(const mpfr_class& v, long long* ipart, const Policy& pol)
{
*ipart = lltrunc(v, pol);
return v - boost::math::tools::real_cast<mpfr_class>(*ipart);
}
template <class T, class U, class Policy>
inline mpfr_class modf(const __gmp_expr<T,U>& v, long long* ipart, const Policy& pol)
{
return modf(static_cast<mpfr_class>(v), ipart, pol);
}
template <class Policy>
inline int iround(mpfr_class const& x, const Policy&)
{
return boost::math::tools::real_cast<int>(boost::math::round(x, typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error< boost::math::policies::throw_on_error> >::type()));
}
template <class T, class U, class Policy>
inline int iround(__gmp_expr<T,U> const& x, const Policy& pol)
{
return iround(static_cast<mpfr_class>(x), pol);
}
template <class Policy>
inline long lround(mpfr_class const& x, const Policy&)
{
return boost::math::tools::real_cast<long>(boost::math::round(x, typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error< boost::math::policies::throw_on_error> >::type()));
}
template <class T, class U, class Policy>
inline long lround(__gmp_expr<T,U> const& x, const Policy& pol)
{
return lround(static_cast<mpfr_class>(x), pol);
}
template <class Policy>
inline long long llround(mpfr_class const& x, const Policy&)
{
return boost::math::tools::real_cast<long long>(boost::math::round(x, typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error< boost::math::policies::throw_on_error> >::type()));
}
template <class T, class U, class Policy>
inline long long llround(__gmp_expr<T,U> const& x, const Policy& pol)
{
return llround(static_cast<mpfr_class>(x), pol);
}
template <class Policy>
inline int itrunc(mpfr_class const& x, const Policy&)
{
return boost::math::tools::real_cast<int>(boost::math::trunc(x, typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error< boost::math::policies::throw_on_error> >::type()));
}
template <class T, class U, class Policy>
inline int itrunc(__gmp_expr<T,U> const& x, const Policy& pol)
{
return itrunc(static_cast<mpfr_class>(x), pol);
}
template <class Policy>
inline long ltrunc(mpfr_class const& x, const Policy&)
{
return boost::math::tools::real_cast<long>(boost::math::trunc(x, typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error< boost::math::policies::throw_on_error> >::type()));
}
template <class T, class U, class Policy>
inline long ltrunc(__gmp_expr<T,U> const& x, const Policy& pol)
{
return ltrunc(static_cast<mpfr_class>(x), pol);
}
template <class Policy>
inline long long lltrunc(mpfr_class const& x, const Policy&)
{
return boost::math::tools::real_cast<long long>(boost::math::trunc(x, typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error< boost::math::policies::throw_on_error> >::type()));
}
template <class T, class U, class Policy>
inline long long lltrunc(__gmp_expr<T,U> const& x, const Policy& pol)
{
return lltrunc(static_cast<mpfr_class>(x), pol);
}
namespace boost{
#ifdef BOOST_MATH_USE_FLOAT128
template<> struct is_convertible<BOOST_MATH_FLOAT128_TYPE, mpfr_class> : public boost::integral_constant<bool, false>{};
#endif
template<> struct is_convertible<long long, mpfr_class> : public boost::integral_constant<bool, false>{};
namespace math{
#if defined(__GNUC__) && (__GNUC__ < 4)
using ::iround;
using ::lround;
using ::llround;
using ::itrunc;
using ::ltrunc;
using ::lltrunc;
using ::modf;
#endif
namespace lanczos{
struct mpfr_lanczos
{
static mpfr_class lanczos_sum(const mpfr_class& z)
{
unsigned long p = z.get_dprec();
if(p <= 72)
return lanczos13UDT::lanczos_sum(z);
else if(p <= 120)
return lanczos22UDT::lanczos_sum(z);
else if(p <= 170)
return lanczos31UDT::lanczos_sum(z);
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::lanczos_sum(z);
}
static mpfr_class lanczos_sum_expG_scaled(const mpfr_class& z)
{
unsigned long p = z.get_dprec();
if(p <= 72)
return lanczos13UDT::lanczos_sum_expG_scaled(z);
else if(p <= 120)
return lanczos22UDT::lanczos_sum_expG_scaled(z);
else if(p <= 170)
return lanczos31UDT::lanczos_sum_expG_scaled(z);
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::lanczos_sum_expG_scaled(z);
}
static mpfr_class lanczos_sum_near_1(const mpfr_class& z)
{
unsigned long p = z.get_dprec();
if(p <= 72)
return lanczos13UDT::lanczos_sum_near_1(z);
else if(p <= 120)
return lanczos22UDT::lanczos_sum_near_1(z);
else if(p <= 170)
return lanczos31UDT::lanczos_sum_near_1(z);
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::lanczos_sum_near_1(z);
}
static mpfr_class lanczos_sum_near_2(const mpfr_class& z)
{
unsigned long p = z.get_dprec();
if(p <= 72)
return lanczos13UDT::lanczos_sum_near_2(z);
else if(p <= 120)
return lanczos22UDT::lanczos_sum_near_2(z);
else if(p <= 170)
return lanczos31UDT::lanczos_sum_near_2(z);
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::lanczos_sum_near_2(z);
}
static mpfr_class g()
{
unsigned long p = mpfr_class::get_dprec();
if(p <= 72)
return lanczos13UDT::g();
else if(p <= 120)
return lanczos22UDT::g();
else if(p <= 170)
return lanczos31UDT::g();
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::g();
}
};
template<class Policy>
struct lanczos<mpfr_class, Policy>
{
typedef mpfr_lanczos type;
};
} // namespace lanczos
namespace constants{
template <class Real, class Policy>
struct construction_traits;
template <class Policy>
struct construction_traits<mpfr_class, Policy>
{
typedef mpl::int_<0> type;
};
}
namespace tools
{
template <class T, class U>
struct promote_arg<__gmp_expr<T,U> >
{ // If T is integral type, then promote to double.
typedef mpfr_class type;
};
template<>
inline int digits<mpfr_class>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class)) BOOST_NOEXCEPT
{
return mpfr_class::get_dprec();
}
namespace detail{
template<class I>
void convert_to_long_result(mpfr_class const& r, I& result)
{
result = 0;
I last_result(0);
mpfr_class t(r);
double term;
do
{
term = real_cast<double>(t);
last_result = result;
result += static_cast<I>(term);
t -= term;
}while(result != last_result);
}
}
template <>
inline mpfr_class real_cast<mpfr_class, long long>(long long t)
{
mpfr_class result;
int expon = 0;
int sign = 1;
if(t < 0)
{
sign = -1;
t = -t;
}
while(t)
{
result += ldexp((double)(t & 0xffffL), expon);
expon += 32;
t >>= 32;
}
return result * sign;
}
template <>
inline unsigned real_cast<unsigned, mpfr_class>(mpfr_class t)
{
return t.get_ui();
}
template <>
inline int real_cast<int, mpfr_class>(mpfr_class t)
{
return t.get_si();
}
template <>
inline double real_cast<double, mpfr_class>(mpfr_class t)
{
return t.get_d();
}
template <>
inline float real_cast<float, mpfr_class>(mpfr_class t)
{
return static_cast<float>(t.get_d());
}
template <>
inline long real_cast<long, mpfr_class>(mpfr_class t)
{
long result;
detail::convert_to_long_result(t, result);
return result;
}
template <>
inline long long real_cast<long long, mpfr_class>(mpfr_class t)
{
long long result;
detail::convert_to_long_result(t, result);
return result;
}
template <>
inline mpfr_class max_value<mpfr_class>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class))
{
static bool has_init = false;
static mpfr_class val;
if(!has_init)
{
val = 0.5;
mpfr_set_exp(val.__get_mp(), mpfr_get_emax());
has_init = true;
}
return val;
}
template <>
inline mpfr_class min_value<mpfr_class>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class))
{
static bool has_init = false;
static mpfr_class val;
if(!has_init)
{
val = 0.5;
mpfr_set_exp(val.__get_mp(), mpfr_get_emin());
has_init = true;
}
return val;
}
template <>
inline mpfr_class log_max_value<mpfr_class>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class))
{
static bool has_init = false;
static mpfr_class val = max_value<mpfr_class>();
if(!has_init)
{
val = log(val);
has_init = true;
}
return val;
}
template <>
inline mpfr_class log_min_value<mpfr_class>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class))
{
static bool has_init = false;
static mpfr_class val = max_value<mpfr_class>();
if(!has_init)
{
val = log(val);
has_init = true;
}
return val;
}
template <>
inline mpfr_class epsilon<mpfr_class>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr_class))
{
return ldexp(mpfr_class(1), 1-boost::math::policies::digits<mpfr_class, boost::math::policies::policy<> >());
}
} // namespace tools
namespace policies{
template <class T, class U, class Policy>
struct evaluation<__gmp_expr<T, U>, Policy>
{
typedef mpfr_class type;
};
}
template <class Policy>
inline mpfr_class skewness(const extreme_value_distribution<mpfr_class, Policy>& /*dist*/)
{
//
// This is 12 * sqrt(6) * zeta(3) / pi^3:
// See http://mathworld.wolfram.com/ExtremeValueDistribution.html
//
return boost::lexical_cast<mpfr_class>("1.1395470994046486574927930193898461120875997958366");
}
template <class Policy>
inline mpfr_class skewness(const rayleigh_distribution<mpfr_class, Policy>& /*dist*/)
{
// using namespace boost::math::constants;
return boost::lexical_cast<mpfr_class>("0.63111065781893713819189935154422777984404221106391");
// 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 Policy>
inline mpfr_class kurtosis(const rayleigh_distribution<mpfr_class, Policy>& /*dist*/)
{
// using namespace boost::math::constants;
return boost::lexical_cast<mpfr_class>("3.2450893006876380628486604106197544154170667057995");
// 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 Policy>
inline mpfr_class kurtosis_excess(const rayleigh_distribution<mpfr_class, Policy>& /*dist*/)
{
//using namespace boost::math::constants;
// Computed using NTL at 150 bit, about 50 decimal digits.
return boost::lexical_cast<mpfr_class>("0.2450893006876380628486604106197544154170667057995");
// return -(6 * pi<RealType>() * pi<RealType>() - 24 * pi<RealType>() + 16) /
// (four_minus_pi<RealType>() * four_minus_pi<RealType>());
} // kurtosis
namespace detail{
//
// Version of Digamma accurate to ~100 decimal digits.
//
template <class Policy>
mpfr_class digamma_imp(mpfr_class x, const mpl::int_<0>* , const Policy& pol)
{
//
// This handles reflection of negative arguments, and all our
// empfr_classor handling, then forwards to the T-specific approximation.
//
BOOST_MATH_STD_USING // ADL of std functions.
mpfr_class result = 0;
//
// Check for negative arguments and use reflection:
//
if(x < 0)
{
// Reflect:
x = 1 - x;
// Argument reduction for tan:
mpfr_class remainder = x - floor(x);
// Shift to negative if > 0.5:
if(remainder > 0.5)
{
remainder -= 1;
}
//
// check for evaluation at a negative pole:
//
if(remainder == 0)
{
return policies::raise_pole_error<mpfr_class>("boost::math::digamma<%1%>(%1%)", 0, (1-x), pol);
}
result = constants::pi<mpfr_class>() / tan(constants::pi<mpfr_class>() * remainder);
}
result += big_digamma(x);
return result;
}
//
// Specialisations of this function provides the initial
// starting guess for Halley iteration:
//
template <class Policy>
inline mpfr_class erf_inv_imp(const mpfr_class& p, const mpfr_class& q, const Policy&, const boost::mpl::int_<64>*)
{
BOOST_MATH_STD_USING // for ADL of std names.
mpfr_class result = 0;
if(p <= 0.5)
{
//
// Evaluate inverse erf using the rational approximation:
//
// x = p(p+10)(Y+R(p))
//
// Where Y is a constant, and R(p) is optimised for a low
// absolute empfr_classor compared to |Y|.
//
// double: Max empfr_classor found: 2.001849e-18
// long double: Max empfr_classor found: 1.017064e-20
// Maximum Deviation Found (actual empfr_classor term at infinite precision) 8.030e-21
//
static const float Y = 0.0891314744949340820313f;
static const mpfr_class P[] = {
-0.000508781949658280665617,
-0.00836874819741736770379,
0.0334806625409744615033,
-0.0126926147662974029034,
-0.0365637971411762664006,
0.0219878681111168899165,
0.00822687874676915743155,
-0.00538772965071242932965
};
static const mpfr_class Q[] = {
1,
-0.970005043303290640362,
-1.56574558234175846809,
1.56221558398423026363,
0.662328840472002992063,
-0.71228902341542847553,
-0.0527396382340099713954,
0.0795283687341571680018,
-0.00233393759374190016776,
0.000886216390456424707504
};
mpfr_class g = p * (p + 10);
mpfr_class r = tools::evaluate_polynomial(P, p) / tools::evaluate_polynomial(Q, p);
result = g * Y + g * r;
}
else if(q >= 0.25)
{
//
// Rational approximation for 0.5 > q >= 0.25
//
// x = sqrt(-2*log(q)) / (Y + R(q))
//
// Where Y is a constant, and R(q) is optimised for a low
// absolute empfr_classor compared to Y.
//
// double : Max empfr_classor found: 7.403372e-17
// long double : Max empfr_classor found: 6.084616e-20
// Maximum Deviation Found (empfr_classor term) 4.811e-20
//
static const float Y = 2.249481201171875f;
static const mpfr_class P[] = {
-0.202433508355938759655,
0.105264680699391713268,
8.37050328343119927838,
17.6447298408374015486,
-18.8510648058714251895,
-44.6382324441786960818,
17.445385985570866523,
21.1294655448340526258,
-3.67192254707729348546
};
static const mpfr_class Q[] = {
1,
6.24264124854247537712,
3.9713437953343869095,
-28.6608180499800029974,
-20.1432634680485188801,
48.5609213108739935468,
10.8268667355460159008,
-22.6436933413139721736,
1.72114765761200282724
};
mpfr_class g = sqrt(-2 * log(q));
mpfr_class xs = q - 0.25;
mpfr_class r = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
result = g / (Y + r);
}
else
{
//
// For q < 0.25 we have a series of rational approximations all
// of the general form:
//
// let: x = sqrt(-log(q))
//
// Then the result is given by:
//
// x(Y+R(x-B))
//
// where Y is a constant, B is the lowest value of x for which
// the approximation is valid, and R(x-B) is optimised for a low
// absolute empfr_classor compared to Y.
//
// Note that almost all code will really go through the first
// or maybe second approximation. After than we're dealing with very
// small input values indeed: 80 and 128 bit long double's go all the
// way down to ~ 1e-5000 so the "tail" is rather long...
//
mpfr_class x = sqrt(-log(q));
if(x < 3)
{
// Max empfr_classor found: 1.089051e-20
static const float Y = 0.807220458984375f;
static const mpfr_class P[] = {
-0.131102781679951906451,
-0.163794047193317060787,
0.117030156341995252019,
0.387079738972604337464,
0.337785538912035898924,
0.142869534408157156766,
0.0290157910005329060432,
0.00214558995388805277169,
-0.679465575181126350155e-6,
0.285225331782217055858e-7,
-0.681149956853776992068e-9
};
static const mpfr_class Q[] = {
1,
3.46625407242567245975,
5.38168345707006855425,
4.77846592945843778382,
2.59301921623620271374,
0.848854343457902036425,
0.152264338295331783612,
0.01105924229346489121
};
mpfr_class xs = x - 1.125;
mpfr_class R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
result = Y * x + R * x;
}
else if(x < 6)
{
// Max empfr_classor found: 8.389174e-21
static const float Y = 0.93995571136474609375f;
static const mpfr_class P[] = {
-0.0350353787183177984712,
-0.00222426529213447927281,
0.0185573306514231072324,
0.00950804701325919603619,
0.00187123492819559223345,
0.000157544617424960554631,
0.460469890584317994083e-5,
-0.230404776911882601748e-9,
0.266339227425782031962e-11
};
static const mpfr_class Q[] = {
1,
1.3653349817554063097,
0.762059164553623404043,
0.220091105764131249824,
0.0341589143670947727934,
0.00263861676657015992959,
0.764675292302794483503e-4
};
mpfr_class xs = x - 3;
mpfr_class R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
result = Y * x + R * x;
}
else if(x < 18)
{
// Max empfr_classor found: 1.481312e-19
static const float Y = 0.98362827301025390625f;
static const mpfr_class P[] = {
-0.0167431005076633737133,
-0.00112951438745580278863,
0.00105628862152492910091,
0.000209386317487588078668,
0.149624783758342370182e-4,
0.449696789927706453732e-6,
0.462596163522878599135e-8,
-0.281128735628831791805e-13,
0.99055709973310326855e-16
};
static const mpfr_class Q[] = {
1,
0.591429344886417493481,
0.138151865749083321638,
0.0160746087093676504695,
0.000964011807005165528527,
0.275335474764726041141e-4,
0.282243172016108031869e-6
};
mpfr_class xs = x - 6;
mpfr_class R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
result = Y * x + R * x;
}
else if(x < 44)
{
// Max empfr_classor found: 5.697761e-20
static const float Y = 0.99714565277099609375f;
static const mpfr_class P[] = {
-0.0024978212791898131227,
-0.779190719229053954292e-5,
0.254723037413027451751e-4,
0.162397777342510920873e-5,
0.396341011304801168516e-7,
0.411632831190944208473e-9,
0.145596286718675035587e-11,
-0.116765012397184275695e-17
};
static const mpfr_class Q[] = {
1,
0.207123112214422517181,
0.0169410838120975906478,
0.000690538265622684595676,
0.145007359818232637924e-4,
0.144437756628144157666e-6,
0.509761276599778486139e-9
};
mpfr_class xs = x - 18;
mpfr_class R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
result = Y * x + R * x;
}
else
{
// Max empfr_classor found: 1.279746e-20
static const float Y = 0.99941349029541015625f;
static const mpfr_class P[] = {
-0.000539042911019078575891,
-0.28398759004727721098e-6,
0.899465114892291446442e-6,
0.229345859265920864296e-7,
0.225561444863500149219e-9,
0.947846627503022684216e-12,
0.135880130108924861008e-14,
-0.348890393399948882918e-21
};
static const mpfr_class Q[] = {
1,
0.0845746234001899436914,
0.00282092984726264681981,
0.468292921940894236786e-4,
0.399968812193862100054e-6,
0.161809290887904476097e-8,
0.231558608310259605225e-11
};
mpfr_class xs = x - 44;
mpfr_class R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
result = Y * x + R * x;
}
}
return result;
}
inline mpfr_class bessel_i0(mpfr_class x)
{
static const mpfr_class P1[] = {
boost::lexical_cast<mpfr_class>("-2.2335582639474375249e+15"),
boost::lexical_cast<mpfr_class>("-5.5050369673018427753e+14"),
boost::lexical_cast<mpfr_class>("-3.2940087627407749166e+13"),
boost::lexical_cast<mpfr_class>("-8.4925101247114157499e+11"),
boost::lexical_cast<mpfr_class>("-1.1912746104985237192e+10"),
boost::lexical_cast<mpfr_class>("-1.0313066708737980747e+08"),
boost::lexical_cast<mpfr_class>("-5.9545626019847898221e+05"),
boost::lexical_cast<mpfr_class>("-2.4125195876041896775e+03"),
boost::lexical_cast<mpfr_class>("-7.0935347449210549190e+00"),
boost::lexical_cast<mpfr_class>("-1.5453977791786851041e-02"),
boost::lexical_cast<mpfr_class>("-2.5172644670688975051e-05"),
boost::lexical_cast<mpfr_class>("-3.0517226450451067446e-08"),
boost::lexical_cast<mpfr_class>("-2.6843448573468483278e-11"),
boost::lexical_cast<mpfr_class>("-1.5982226675653184646e-14"),
boost::lexical_cast<mpfr_class>("-5.2487866627945699800e-18"),
};
static const mpfr_class Q1[] = {
boost::lexical_cast<mpfr_class>("-2.2335582639474375245e+15"),
boost::lexical_cast<mpfr_class>("7.8858692566751002988e+12"),
boost::lexical_cast<mpfr_class>("-1.2207067397808979846e+10"),
boost::lexical_cast<mpfr_class>("1.0377081058062166144e+07"),
boost::lexical_cast<mpfr_class>("-4.8527560179962773045e+03"),
boost::lexical_cast<mpfr_class>("1.0"),
};
static const mpfr_class P2[] = {
boost::lexical_cast<mpfr_class>("-2.2210262233306573296e-04"),
boost::lexical_cast<mpfr_class>("1.3067392038106924055e-02"),
boost::lexical_cast<mpfr_class>("-4.4700805721174453923e-01"),
boost::lexical_cast<mpfr_class>("5.5674518371240761397e+00"),
boost::lexical_cast<mpfr_class>("-2.3517945679239481621e+01"),
boost::lexical_cast<mpfr_class>("3.1611322818701131207e+01"),
boost::lexical_cast<mpfr_class>("-9.6090021968656180000e+00"),
};
static const mpfr_class Q2[] = {
boost::lexical_cast<mpfr_class>("-5.5194330231005480228e-04"),
boost::lexical_cast<mpfr_class>("3.2547697594819615062e-02"),
boost::lexical_cast<mpfr_class>("-1.1151759188741312645e+00"),
boost::lexical_cast<mpfr_class>("1.3982595353892851542e+01"),
boost::lexical_cast<mpfr_class>("-6.0228002066743340583e+01"),
boost::lexical_cast<mpfr_class>("8.5539563258012929600e+01"),
boost::lexical_cast<mpfr_class>("-3.1446690275135491500e+01"),
boost::lexical_cast<mpfr_class>("1.0"),
};
mpfr_class 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<mpfr_class>(1);
}
if (x <= 15) // x in (0, 15]
{
mpfr_class y = x * x;
value = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
}
else // x in (15, \infty)
{
mpfr_class y = 1 / x - mpfr_class(1) / 15;
r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
factor = exp(x) / sqrt(x);
value = factor * r;
}
return value;
}
inline mpfr_class bessel_i1(mpfr_class x)
{
static const mpfr_class P1[] = {
static_cast<mpfr_class>("-1.4577180278143463643e+15"),
static_cast<mpfr_class>("-1.7732037840791591320e+14"),
static_cast<mpfr_class>("-6.9876779648010090070e+12"),
static_cast<mpfr_class>("-1.3357437682275493024e+11"),
static_cast<mpfr_class>("-1.4828267606612366099e+09"),
static_cast<mpfr_class>("-1.0588550724769347106e+07"),
static_cast<mpfr_class>("-5.1894091982308017540e+04"),
static_cast<mpfr_class>("-1.8225946631657315931e+02"),
static_cast<mpfr_class>("-4.7207090827310162436e-01"),
static_cast<mpfr_class>("-9.1746443287817501309e-04"),
static_cast<mpfr_class>("-1.3466829827635152875e-06"),
static_cast<mpfr_class>("-1.4831904935994647675e-09"),
static_cast<mpfr_class>("-1.1928788903603238754e-12"),
static_cast<mpfr_class>("-6.5245515583151902910e-16"),
static_cast<mpfr_class>("-1.9705291802535139930e-19"),
};
static const mpfr_class Q1[] = {
static_cast<mpfr_class>("-2.9154360556286927285e+15"),
static_cast<mpfr_class>("9.7887501377547640438e+12"),
static_cast<mpfr_class>("-1.4386907088588283434e+10"),
static_cast<mpfr_class>("1.1594225856856884006e+07"),
static_cast<mpfr_class>("-5.1326864679904189920e+03"),
static_cast<mpfr_class>("1.0"),
};
static const mpfr_class P2[] = {
static_cast<mpfr_class>("1.4582087408985668208e-05"),
static_cast<mpfr_class>("-8.9359825138577646443e-04"),
static_cast<mpfr_class>("2.9204895411257790122e-02"),
static_cast<mpfr_class>("-3.4198728018058047439e-01"),
static_cast<mpfr_class>("1.3960118277609544334e+00"),
static_cast<mpfr_class>("-1.9746376087200685843e+00"),
static_cast<mpfr_class>("8.5591872901933459000e-01"),
static_cast<mpfr_class>("-6.0437159056137599999e-02"),
};
static const mpfr_class Q2[] = {
static_cast<mpfr_class>("3.7510433111922824643e-05"),
static_cast<mpfr_class>("-2.2835624489492512649e-03"),
static_cast<mpfr_class>("7.4212010813186530069e-02"),
static_cast<mpfr_class>("-8.5017476463217924408e-01"),
static_cast<mpfr_class>("3.2593714889036996297e+00"),
static_cast<mpfr_class>("-3.8806586721556593450e+00"),
static_cast<mpfr_class>("1.0"),
};
mpfr_class value, factor, r, w;
BOOST_MATH_STD_USING
using namespace boost::math::tools;
w = abs(x);
if (x == 0)
{
return static_cast<mpfr_class>(0);
}
if (w <= 15) // w in (0, 15]
{
mpfr_class y = x * x;
r = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
factor = w;
value = factor * r;
}
else // w in (15, \infty)
{
mpfr_class y = 1 / w - mpfr_class(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;
}
} // namespace detail
}
template<> struct is_convertible<long double, mpfr_class> : public mpl::false_{};
}
#endif // BOOST_MATH_MPLFR_BINDINGS_HPP

View File

@@ -0,0 +1,898 @@
// Copyright John Maddock 2008.
// 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)
//
// Wrapper that works with mpfr::mpreal defined in gmpfrxx.h
// See http://math.berkeley.edu/~wilken/code/gmpfrxx/
// Also requires the gmp and mpfr libraries.
//
#ifndef BOOST_MATH_MPREAL_BINDINGS_HPP
#define BOOST_MATH_MPREAL_BINDINGS_HPP
#include <boost/config.hpp>
#include <boost/lexical_cast.hpp>
#ifdef BOOST_MSVC
//
// We get a lot of warnings from the gmp, mpfr and gmpfrxx headers,
// disable them here, so we only see warnings from *our* code:
//
#pragma warning(push)
#pragma warning(disable: 4127 4800 4512)
#endif
#include <mpreal.h>
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#include <boost/math/tools/precision.hpp>
#include <boost/math/tools/real_cast.hpp>
#include <boost/math/policies/policy.hpp>
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/bindings/detail/big_digamma.hpp>
#include <boost/math/bindings/detail/big_lanczos.hpp>
namespace mpfr{
template <class T>
inline mpreal operator + (const mpreal& r, const T& t){ return r + mpreal(t); }
template <class T>
inline mpreal operator - (const mpreal& r, const T& t){ return r - mpreal(t); }
template <class T>
inline mpreal operator * (const mpreal& r, const T& t){ return r * mpreal(t); }
template <class T>
inline mpreal operator / (const mpreal& r, const T& t){ return r / mpreal(t); }
template <class T>
inline mpreal operator + (const T& t, const mpreal& r){ return mpreal(t) + r; }
template <class T>
inline mpreal operator - (const T& t, const mpreal& r){ return mpreal(t) - r; }
template <class T>
inline mpreal operator * (const T& t, const mpreal& r){ return mpreal(t) * r; }
template <class T>
inline mpreal operator / (const T& t, const mpreal& r){ return mpreal(t) / r; }
template <class T>
inline bool operator == (const mpreal& r, const T& t){ return r == mpreal(t); }
template <class T>
inline bool operator != (const mpreal& r, const T& t){ return r != mpreal(t); }
template <class T>
inline bool operator <= (const mpreal& r, const T& t){ return r <= mpreal(t); }
template <class T>
inline bool operator >= (const mpreal& r, const T& t){ return r >= mpreal(t); }
template <class T>
inline bool operator < (const mpreal& r, const T& t){ return r < mpreal(t); }
template <class T>
inline bool operator > (const mpreal& r, const T& t){ return r > mpreal(t); }
template <class T>
inline bool operator == (const T& t, const mpreal& r){ return mpreal(t) == r; }
template <class T>
inline bool operator != (const T& t, const mpreal& r){ return mpreal(t) != r; }
template <class T>
inline bool operator <= (const T& t, const mpreal& r){ return mpreal(t) <= r; }
template <class T>
inline bool operator >= (const T& t, const mpreal& r){ return mpreal(t) >= r; }
template <class T>
inline bool operator < (const T& t, const mpreal& r){ return mpreal(t) < r; }
template <class T>
inline bool operator > (const T& t, const mpreal& r){ return mpreal(t) > r; }
/*
inline mpfr::mpreal fabs(const mpfr::mpreal& v)
{
return abs(v);
}
inline mpfr::mpreal pow(const mpfr::mpreal& b, const mpfr::mpreal e)
{
mpfr::mpreal result;
mpfr_pow(result.__get_mp(), b.__get_mp(), e.__get_mp(), GMP_RNDN);
return result;
}
*/
inline mpfr::mpreal ldexp(const mpfr::mpreal& v, int e)
{
return mpfr::ldexp(v, static_cast<mp_exp_t>(e));
}
inline mpfr::mpreal frexp(const mpfr::mpreal& v, int* expon)
{
mp_exp_t e;
mpfr::mpreal r = mpfr::frexp(v, &e);
*expon = e;
return r;
}
#if (MPFR_VERSION < MPFR_VERSION_NUM(2,4,0))
mpfr::mpreal fmod(const mpfr::mpreal& v1, const mpfr::mpreal& v2)
{
mpfr::mpreal n;
if(v1 < 0)
n = ceil(v1 / v2);
else
n = floor(v1 / v2);
return v1 - n * v2;
}
#endif
template <class Policy>
inline mpfr::mpreal modf(const mpfr::mpreal& v, long long* ipart, const Policy& pol)
{
*ipart = lltrunc(v, pol);
return v - boost::math::tools::real_cast<mpfr::mpreal>(*ipart);
}
template <class Policy>
inline int iround(mpfr::mpreal const& x, const Policy& pol)
{
return boost::math::tools::real_cast<int>(boost::math::round(x, pol));
}
template <class Policy>
inline long lround(mpfr::mpreal const& x, const Policy& pol)
{
return boost::math::tools::real_cast<long>(boost::math::round(x, pol));
}
template <class Policy>
inline long long llround(mpfr::mpreal const& x, const Policy& pol)
{
return boost::math::tools::real_cast<long long>(boost::math::round(x, pol));
}
template <class Policy>
inline int itrunc(mpfr::mpreal const& x, const Policy& pol)
{
return boost::math::tools::real_cast<int>(boost::math::trunc(x, pol));
}
template <class Policy>
inline long ltrunc(mpfr::mpreal const& x, const Policy& pol)
{
return boost::math::tools::real_cast<long>(boost::math::trunc(x, pol));
}
template <class Policy>
inline long long lltrunc(mpfr::mpreal const& x, const Policy& pol)
{
return boost::math::tools::real_cast<long long>(boost::math::trunc(x, pol));
}
}
namespace boost{ namespace math{
#if defined(__GNUC__) && (__GNUC__ < 4)
using ::iround;
using ::lround;
using ::llround;
using ::itrunc;
using ::ltrunc;
using ::lltrunc;
using ::modf;
#endif
namespace lanczos{
struct mpreal_lanczos
{
static mpfr::mpreal lanczos_sum(const mpfr::mpreal& z)
{
unsigned long p = z.get_default_prec();
if(p <= 72)
return lanczos13UDT::lanczos_sum(z);
else if(p <= 120)
return lanczos22UDT::lanczos_sum(z);
else if(p <= 170)
return lanczos31UDT::lanczos_sum(z);
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::lanczos_sum(z);
}
static mpfr::mpreal lanczos_sum_expG_scaled(const mpfr::mpreal& z)
{
unsigned long p = z.get_default_prec();
if(p <= 72)
return lanczos13UDT::lanczos_sum_expG_scaled(z);
else if(p <= 120)
return lanczos22UDT::lanczos_sum_expG_scaled(z);
else if(p <= 170)
return lanczos31UDT::lanczos_sum_expG_scaled(z);
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::lanczos_sum_expG_scaled(z);
}
static mpfr::mpreal lanczos_sum_near_1(const mpfr::mpreal& z)
{
unsigned long p = z.get_default_prec();
if(p <= 72)
return lanczos13UDT::lanczos_sum_near_1(z);
else if(p <= 120)
return lanczos22UDT::lanczos_sum_near_1(z);
else if(p <= 170)
return lanczos31UDT::lanczos_sum_near_1(z);
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::lanczos_sum_near_1(z);
}
static mpfr::mpreal lanczos_sum_near_2(const mpfr::mpreal& z)
{
unsigned long p = z.get_default_prec();
if(p <= 72)
return lanczos13UDT::lanczos_sum_near_2(z);
else if(p <= 120)
return lanczos22UDT::lanczos_sum_near_2(z);
else if(p <= 170)
return lanczos31UDT::lanczos_sum_near_2(z);
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::lanczos_sum_near_2(z);
}
static mpfr::mpreal g()
{
unsigned long p = mpfr::mpreal::get_default_prec();
if(p <= 72)
return lanczos13UDT::g();
else if(p <= 120)
return lanczos22UDT::g();
else if(p <= 170)
return lanczos31UDT::g();
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::g();
}
};
template<class Policy>
struct lanczos<mpfr::mpreal, Policy>
{
typedef mpreal_lanczos type;
};
} // namespace lanczos
namespace tools
{
template<>
inline int digits<mpfr::mpreal>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr::mpreal))
{
return mpfr::mpreal::get_default_prec();
}
namespace detail{
template<class I>
void convert_to_long_result(mpfr::mpreal const& r, I& result)
{
result = 0;
I last_result(0);
mpfr::mpreal t(r);
double term;
do
{
term = real_cast<double>(t);
last_result = result;
result += static_cast<I>(term);
t -= term;
}while(result != last_result);
}
}
template <>
inline mpfr::mpreal real_cast<mpfr::mpreal, long long>(long long t)
{
mpfr::mpreal result;
int expon = 0;
int sign = 1;
if(t < 0)
{
sign = -1;
t = -t;
}
while(t)
{
result += ldexp((double)(t & 0xffffL), expon);
expon += 32;
t >>= 32;
}
return result * sign;
}
/*
template <>
inline unsigned real_cast<unsigned, mpfr::mpreal>(mpfr::mpreal t)
{
return t.get_ui();
}
template <>
inline int real_cast<int, mpfr::mpreal>(mpfr::mpreal t)
{
return t.get_si();
}
template <>
inline double real_cast<double, mpfr::mpreal>(mpfr::mpreal t)
{
return t.get_d();
}
template <>
inline float real_cast<float, mpfr::mpreal>(mpfr::mpreal t)
{
return static_cast<float>(t.get_d());
}
template <>
inline long real_cast<long, mpfr::mpreal>(mpfr::mpreal t)
{
long result;
detail::convert_to_long_result(t, result);
return result;
}
*/
template <>
inline long long real_cast<long long, mpfr::mpreal>(mpfr::mpreal t)
{
long long result;
detail::convert_to_long_result(t, result);
return result;
}
template <>
inline mpfr::mpreal max_value<mpfr::mpreal>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr::mpreal))
{
static bool has_init = false;
static mpfr::mpreal val(0.5);
if(!has_init)
{
val = ldexp(val, mpfr_get_emax());
has_init = true;
}
return val;
}
template <>
inline mpfr::mpreal min_value<mpfr::mpreal>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr::mpreal))
{
static bool has_init = false;
static mpfr::mpreal val(0.5);
if(!has_init)
{
val = ldexp(val, mpfr_get_emin());
has_init = true;
}
return val;
}
template <>
inline mpfr::mpreal log_max_value<mpfr::mpreal>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr::mpreal))
{
static bool has_init = false;
static mpfr::mpreal val = max_value<mpfr::mpreal>();
if(!has_init)
{
val = log(val);
has_init = true;
}
return val;
}
template <>
inline mpfr::mpreal log_min_value<mpfr::mpreal>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr::mpreal))
{
static bool has_init = false;
static mpfr::mpreal val = max_value<mpfr::mpreal>();
if(!has_init)
{
val = log(val);
has_init = true;
}
return val;
}
template <>
inline mpfr::mpreal epsilon<mpfr::mpreal>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpfr::mpreal))
{
return ldexp(mpfr::mpreal(1), 1-boost::math::policies::digits<mpfr::mpreal, boost::math::policies::policy<> >());
}
} // namespace tools
template <class Policy>
inline mpfr::mpreal skewness(const extreme_value_distribution<mpfr::mpreal, Policy>& /*dist*/)
{
//
// This is 12 * sqrt(6) * zeta(3) / pi^3:
// See http://mathworld.wolfram.com/ExtremeValueDistribution.html
//
return boost::lexical_cast<mpfr::mpreal>("1.1395470994046486574927930193898461120875997958366");
}
template <class Policy>
inline mpfr::mpreal skewness(const rayleigh_distribution<mpfr::mpreal, Policy>& /*dist*/)
{
// using namespace boost::math::constants;
return boost::lexical_cast<mpfr::mpreal>("0.63111065781893713819189935154422777984404221106391");
// 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 Policy>
inline mpfr::mpreal kurtosis(const rayleigh_distribution<mpfr::mpreal, Policy>& /*dist*/)
{
// using namespace boost::math::constants;
return boost::lexical_cast<mpfr::mpreal>("3.2450893006876380628486604106197544154170667057995");
// 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 Policy>
inline mpfr::mpreal kurtosis_excess(const rayleigh_distribution<mpfr::mpreal, Policy>& /*dist*/)
{
//using namespace boost::math::constants;
// Computed using NTL at 150 bit, about 50 decimal digits.
return boost::lexical_cast<mpfr::mpreal>("0.2450893006876380628486604106197544154170667057995");
// return -(6 * pi<RealType>() * pi<RealType>() - 24 * pi<RealType>() + 16) /
// (four_minus_pi<RealType>() * four_minus_pi<RealType>());
} // kurtosis
namespace detail{
//
// Version of Digamma accurate to ~100 decimal digits.
//
template <class Policy>
mpfr::mpreal digamma_imp(mpfr::mpreal x, const mpl::int_<0>* , const Policy& pol)
{
//
// This handles reflection of negative arguments, and all our
// empfr_classor handling, then forwards to the T-specific approximation.
//
BOOST_MATH_STD_USING // ADL of std functions.
mpfr::mpreal result = 0;
//
// Check for negative arguments and use reflection:
//
if(x < 0)
{
// Reflect:
x = 1 - x;
// Argument reduction for tan:
mpfr::mpreal remainder = x - floor(x);
// Shift to negative if > 0.5:
if(remainder > 0.5)
{
remainder -= 1;
}
//
// check for evaluation at a negative pole:
//
if(remainder == 0)
{
return policies::raise_pole_error<mpfr::mpreal>("boost::math::digamma<%1%>(%1%)", 0, (1-x), pol);
}
result = constants::pi<mpfr::mpreal>() / tan(constants::pi<mpfr::mpreal>() * remainder);
}
result += big_digamma(x);
return result;
}
//
// Specialisations of this function provides the initial
// starting guess for Halley iteration:
//
template <class Policy>
mpfr::mpreal erf_inv_imp(const mpfr::mpreal& p, const mpfr::mpreal& q, const Policy&, const boost::mpl::int_<64>*)
{
BOOST_MATH_STD_USING // for ADL of std names.
mpfr::mpreal result = 0;
if(p <= 0.5)
{
//
// Evaluate inverse erf using the rational approximation:
//
// x = p(p+10)(Y+R(p))
//
// Where Y is a constant, and R(p) is optimised for a low
// absolute empfr_classor compared to |Y|.
//
// double: Max empfr_classor found: 2.001849e-18
// long double: Max empfr_classor found: 1.017064e-20
// Maximum Deviation Found (actual empfr_classor term at infinite precision) 8.030e-21
//
static const float Y = 0.0891314744949340820313f;
static const mpfr::mpreal P[] = {
-0.000508781949658280665617,
-0.00836874819741736770379,
0.0334806625409744615033,
-0.0126926147662974029034,
-0.0365637971411762664006,
0.0219878681111168899165,
0.00822687874676915743155,
-0.00538772965071242932965
};
static const mpfr::mpreal Q[] = {
1,
-0.970005043303290640362,
-1.56574558234175846809,
1.56221558398423026363,
0.662328840472002992063,
-0.71228902341542847553,
-0.0527396382340099713954,
0.0795283687341571680018,
-0.00233393759374190016776,
0.000886216390456424707504
};
mpfr::mpreal g = p * (p + 10);
mpfr::mpreal r = tools::evaluate_polynomial(P, p) / tools::evaluate_polynomial(Q, p);
result = g * Y + g * r;
}
else if(q >= 0.25)
{
//
// Rational approximation for 0.5 > q >= 0.25
//
// x = sqrt(-2*log(q)) / (Y + R(q))
//
// Where Y is a constant, and R(q) is optimised for a low
// absolute empfr_classor compared to Y.
//
// double : Max empfr_classor found: 7.403372e-17
// long double : Max empfr_classor found: 6.084616e-20
// Maximum Deviation Found (empfr_classor term) 4.811e-20
//
static const float Y = 2.249481201171875f;
static const mpfr::mpreal P[] = {
-0.202433508355938759655,
0.105264680699391713268,
8.37050328343119927838,
17.6447298408374015486,
-18.8510648058714251895,
-44.6382324441786960818,
17.445385985570866523,
21.1294655448340526258,
-3.67192254707729348546
};
static const mpfr::mpreal Q[] = {
1,
6.24264124854247537712,
3.9713437953343869095,
-28.6608180499800029974,
-20.1432634680485188801,
48.5609213108739935468,
10.8268667355460159008,
-22.6436933413139721736,
1.72114765761200282724
};
mpfr::mpreal g = sqrt(-2 * log(q));
mpfr::mpreal xs = q - 0.25;
mpfr::mpreal r = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
result = g / (Y + r);
}
else
{
//
// For q < 0.25 we have a series of rational approximations all
// of the general form:
//
// let: x = sqrt(-log(q))
//
// Then the result is given by:
//
// x(Y+R(x-B))
//
// where Y is a constant, B is the lowest value of x for which
// the approximation is valid, and R(x-B) is optimised for a low
// absolute empfr_classor compared to Y.
//
// Note that almost all code will really go through the first
// or maybe second approximation. After than we're dealing with very
// small input values indeed: 80 and 128 bit long double's go all the
// way down to ~ 1e-5000 so the "tail" is rather long...
//
mpfr::mpreal x = sqrt(-log(q));
if(x < 3)
{
// Max empfr_classor found: 1.089051e-20
static const float Y = 0.807220458984375f;
static const mpfr::mpreal P[] = {
-0.131102781679951906451,
-0.163794047193317060787,
0.117030156341995252019,
0.387079738972604337464,
0.337785538912035898924,
0.142869534408157156766,
0.0290157910005329060432,
0.00214558995388805277169,
-0.679465575181126350155e-6,
0.285225331782217055858e-7,
-0.681149956853776992068e-9
};
static const mpfr::mpreal Q[] = {
1,
3.46625407242567245975,
5.38168345707006855425,
4.77846592945843778382,
2.59301921623620271374,
0.848854343457902036425,
0.152264338295331783612,
0.01105924229346489121
};
mpfr::mpreal xs = x - 1.125;
mpfr::mpreal R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
result = Y * x + R * x;
}
else if(x < 6)
{
// Max empfr_classor found: 8.389174e-21
static const float Y = 0.93995571136474609375f;
static const mpfr::mpreal P[] = {
-0.0350353787183177984712,
-0.00222426529213447927281,
0.0185573306514231072324,
0.00950804701325919603619,
0.00187123492819559223345,
0.000157544617424960554631,
0.460469890584317994083e-5,
-0.230404776911882601748e-9,
0.266339227425782031962e-11
};
static const mpfr::mpreal Q[] = {
1,
1.3653349817554063097,
0.762059164553623404043,
0.220091105764131249824,
0.0341589143670947727934,
0.00263861676657015992959,
0.764675292302794483503e-4
};
mpfr::mpreal xs = x - 3;
mpfr::mpreal R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
result = Y * x + R * x;
}
else if(x < 18)
{
// Max empfr_classor found: 1.481312e-19
static const float Y = 0.98362827301025390625f;
static const mpfr::mpreal P[] = {
-0.0167431005076633737133,
-0.00112951438745580278863,
0.00105628862152492910091,
0.000209386317487588078668,
0.149624783758342370182e-4,
0.449696789927706453732e-6,
0.462596163522878599135e-8,
-0.281128735628831791805e-13,
0.99055709973310326855e-16
};
static const mpfr::mpreal Q[] = {
1,
0.591429344886417493481,
0.138151865749083321638,
0.0160746087093676504695,
0.000964011807005165528527,
0.275335474764726041141e-4,
0.282243172016108031869e-6
};
mpfr::mpreal xs = x - 6;
mpfr::mpreal R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
result = Y * x + R * x;
}
else if(x < 44)
{
// Max empfr_classor found: 5.697761e-20
static const float Y = 0.99714565277099609375f;
static const mpfr::mpreal P[] = {
-0.0024978212791898131227,
-0.779190719229053954292e-5,
0.254723037413027451751e-4,
0.162397777342510920873e-5,
0.396341011304801168516e-7,
0.411632831190944208473e-9,
0.145596286718675035587e-11,
-0.116765012397184275695e-17
};
static const mpfr::mpreal Q[] = {
1,
0.207123112214422517181,
0.0169410838120975906478,
0.000690538265622684595676,
0.145007359818232637924e-4,
0.144437756628144157666e-6,
0.509761276599778486139e-9
};
mpfr::mpreal xs = x - 18;
mpfr::mpreal R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
result = Y * x + R * x;
}
else
{
// Max empfr_classor found: 1.279746e-20
static const float Y = 0.99941349029541015625f;
static const mpfr::mpreal P[] = {
-0.000539042911019078575891,
-0.28398759004727721098e-6,
0.899465114892291446442e-6,
0.229345859265920864296e-7,
0.225561444863500149219e-9,
0.947846627503022684216e-12,
0.135880130108924861008e-14,
-0.348890393399948882918e-21
};
static const mpfr::mpreal Q[] = {
1,
0.0845746234001899436914,
0.00282092984726264681981,
0.468292921940894236786e-4,
0.399968812193862100054e-6,
0.161809290887904476097e-8,
0.231558608310259605225e-11
};
mpfr::mpreal xs = x - 44;
mpfr::mpreal R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
result = Y * x + R * x;
}
}
return result;
}
inline mpfr::mpreal bessel_i0(mpfr::mpreal x)
{
static const mpfr::mpreal P1[] = {
boost::lexical_cast<mpfr::mpreal>("-2.2335582639474375249e+15"),
boost::lexical_cast<mpfr::mpreal>("-5.5050369673018427753e+14"),
boost::lexical_cast<mpfr::mpreal>("-3.2940087627407749166e+13"),
boost::lexical_cast<mpfr::mpreal>("-8.4925101247114157499e+11"),
boost::lexical_cast<mpfr::mpreal>("-1.1912746104985237192e+10"),
boost::lexical_cast<mpfr::mpreal>("-1.0313066708737980747e+08"),
boost::lexical_cast<mpfr::mpreal>("-5.9545626019847898221e+05"),
boost::lexical_cast<mpfr::mpreal>("-2.4125195876041896775e+03"),
boost::lexical_cast<mpfr::mpreal>("-7.0935347449210549190e+00"),
boost::lexical_cast<mpfr::mpreal>("-1.5453977791786851041e-02"),
boost::lexical_cast<mpfr::mpreal>("-2.5172644670688975051e-05"),
boost::lexical_cast<mpfr::mpreal>("-3.0517226450451067446e-08"),
boost::lexical_cast<mpfr::mpreal>("-2.6843448573468483278e-11"),
boost::lexical_cast<mpfr::mpreal>("-1.5982226675653184646e-14"),
boost::lexical_cast<mpfr::mpreal>("-5.2487866627945699800e-18"),
};
static const mpfr::mpreal Q1[] = {
boost::lexical_cast<mpfr::mpreal>("-2.2335582639474375245e+15"),
boost::lexical_cast<mpfr::mpreal>("7.8858692566751002988e+12"),
boost::lexical_cast<mpfr::mpreal>("-1.2207067397808979846e+10"),
boost::lexical_cast<mpfr::mpreal>("1.0377081058062166144e+07"),
boost::lexical_cast<mpfr::mpreal>("-4.8527560179962773045e+03"),
boost::lexical_cast<mpfr::mpreal>("1.0"),
};
static const mpfr::mpreal P2[] = {
boost::lexical_cast<mpfr::mpreal>("-2.2210262233306573296e-04"),
boost::lexical_cast<mpfr::mpreal>("1.3067392038106924055e-02"),
boost::lexical_cast<mpfr::mpreal>("-4.4700805721174453923e-01"),
boost::lexical_cast<mpfr::mpreal>("5.5674518371240761397e+00"),
boost::lexical_cast<mpfr::mpreal>("-2.3517945679239481621e+01"),
boost::lexical_cast<mpfr::mpreal>("3.1611322818701131207e+01"),
boost::lexical_cast<mpfr::mpreal>("-9.6090021968656180000e+00"),
};
static const mpfr::mpreal Q2[] = {
boost::lexical_cast<mpfr::mpreal>("-5.5194330231005480228e-04"),
boost::lexical_cast<mpfr::mpreal>("3.2547697594819615062e-02"),
boost::lexical_cast<mpfr::mpreal>("-1.1151759188741312645e+00"),
boost::lexical_cast<mpfr::mpreal>("1.3982595353892851542e+01"),
boost::lexical_cast<mpfr::mpreal>("-6.0228002066743340583e+01"),
boost::lexical_cast<mpfr::mpreal>("8.5539563258012929600e+01"),
boost::lexical_cast<mpfr::mpreal>("-3.1446690275135491500e+01"),
boost::lexical_cast<mpfr::mpreal>("1.0"),
};
mpfr::mpreal 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<mpfr::mpreal>(1);
}
if (x <= 15) // x in (0, 15]
{
mpfr::mpreal y = x * x;
value = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
}
else // x in (15, \infty)
{
mpfr::mpreal y = 1 / x - mpfr::mpreal(1) / 15;
r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
factor = exp(x) / sqrt(x);
value = factor * r;
}
return value;
}
inline mpfr::mpreal bessel_i1(mpfr::mpreal x)
{
static const mpfr::mpreal P1[] = {
static_cast<mpfr::mpreal>("-1.4577180278143463643e+15"),
static_cast<mpfr::mpreal>("-1.7732037840791591320e+14"),
static_cast<mpfr::mpreal>("-6.9876779648010090070e+12"),
static_cast<mpfr::mpreal>("-1.3357437682275493024e+11"),
static_cast<mpfr::mpreal>("-1.4828267606612366099e+09"),
static_cast<mpfr::mpreal>("-1.0588550724769347106e+07"),
static_cast<mpfr::mpreal>("-5.1894091982308017540e+04"),
static_cast<mpfr::mpreal>("-1.8225946631657315931e+02"),
static_cast<mpfr::mpreal>("-4.7207090827310162436e-01"),
static_cast<mpfr::mpreal>("-9.1746443287817501309e-04"),
static_cast<mpfr::mpreal>("-1.3466829827635152875e-06"),
static_cast<mpfr::mpreal>("-1.4831904935994647675e-09"),
static_cast<mpfr::mpreal>("-1.1928788903603238754e-12"),
static_cast<mpfr::mpreal>("-6.5245515583151902910e-16"),
static_cast<mpfr::mpreal>("-1.9705291802535139930e-19"),
};
static const mpfr::mpreal Q1[] = {
static_cast<mpfr::mpreal>("-2.9154360556286927285e+15"),
static_cast<mpfr::mpreal>("9.7887501377547640438e+12"),
static_cast<mpfr::mpreal>("-1.4386907088588283434e+10"),
static_cast<mpfr::mpreal>("1.1594225856856884006e+07"),
static_cast<mpfr::mpreal>("-5.1326864679904189920e+03"),
static_cast<mpfr::mpreal>("1.0"),
};
static const mpfr::mpreal P2[] = {
static_cast<mpfr::mpreal>("1.4582087408985668208e-05"),
static_cast<mpfr::mpreal>("-8.9359825138577646443e-04"),
static_cast<mpfr::mpreal>("2.9204895411257790122e-02"),
static_cast<mpfr::mpreal>("-3.4198728018058047439e-01"),
static_cast<mpfr::mpreal>("1.3960118277609544334e+00"),
static_cast<mpfr::mpreal>("-1.9746376087200685843e+00"),
static_cast<mpfr::mpreal>("8.5591872901933459000e-01"),
static_cast<mpfr::mpreal>("-6.0437159056137599999e-02"),
};
static const mpfr::mpreal Q2[] = {
static_cast<mpfr::mpreal>("3.7510433111922824643e-05"),
static_cast<mpfr::mpreal>("-2.2835624489492512649e-03"),
static_cast<mpfr::mpreal>("7.4212010813186530069e-02"),
static_cast<mpfr::mpreal>("-8.5017476463217924408e-01"),
static_cast<mpfr::mpreal>("3.2593714889036996297e+00"),
static_cast<mpfr::mpreal>("-3.8806586721556593450e+00"),
static_cast<mpfr::mpreal>("1.0"),
};
mpfr::mpreal value, factor, r, w;
BOOST_MATH_STD_USING
using namespace boost::math::tools;
w = abs(x);
if (x == 0)
{
return static_cast<mpfr::mpreal>(0);
}
if (w <= 15) // w in (0, 15]
{
mpfr::mpreal y = x * x;
r = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
factor = w;
value = factor * r;
}
else // w in (15, \infty)
{
mpfr::mpreal y = 1 / w - mpfr::mpreal(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;
}
} // namespace detail
} // namespace math
}
#endif // BOOST_MATH_MPLFR_BINDINGS_HPP

View File

@@ -0,0 +1,884 @@
// 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_NTL_RR_HPP
#define BOOST_MATH_NTL_RR_HPP
#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 <boost/math/bindings/detail/big_digamma.hpp>
#include <boost/math/bindings/detail/big_lanczos.hpp>
#include <ostream>
#include <istream>
#include <boost/config/no_tr1/cmath.hpp>
#include <NTL/RR.h>
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(boost::ulong_long_type c)
{
assign_large_int(c);
}
RR(boost::long_long_type 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=(boost::long_long_type c) { assign_large_int(c); return *this; }
RR& operator=(boost::ulong_long_type 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)
{
::NTL::RR v;
is >> v;
a = v;
return is;
}
} // namespace ntl
namespace lanczos{
struct ntl_lanczos
{
static ntl::RR lanczos_sum(const ntl::RR& z)
{
unsigned long p = ntl::RR::precision();
if(p <= 72)
return lanczos13UDT::lanczos_sum(z);
else if(p <= 120)
return lanczos22UDT::lanczos_sum(z);
else if(p <= 170)
return lanczos31UDT::lanczos_sum(z);
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::lanczos_sum(z);
}
static ntl::RR lanczos_sum_expG_scaled(const ntl::RR& z)
{
unsigned long p = ntl::RR::precision();
if(p <= 72)
return lanczos13UDT::lanczos_sum_expG_scaled(z);
else if(p <= 120)
return lanczos22UDT::lanczos_sum_expG_scaled(z);
else if(p <= 170)
return lanczos31UDT::lanczos_sum_expG_scaled(z);
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::lanczos_sum_expG_scaled(z);
}
static ntl::RR lanczos_sum_near_1(const ntl::RR& z)
{
unsigned long p = ntl::RR::precision();
if(p <= 72)
return lanczos13UDT::lanczos_sum_near_1(z);
else if(p <= 120)
return lanczos22UDT::lanczos_sum_near_1(z);
else if(p <= 170)
return lanczos31UDT::lanczos_sum_near_1(z);
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::lanczos_sum_near_1(z);
}
static ntl::RR lanczos_sum_near_2(const ntl::RR& z)
{
unsigned long p = ntl::RR::precision();
if(p <= 72)
return lanczos13UDT::lanczos_sum_near_2(z);
else if(p <= 120)
return lanczos22UDT::lanczos_sum_near_2(z);
else if(p <= 170)
return lanczos31UDT::lanczos_sum_near_2(z);
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::lanczos_sum_near_2(z);
}
static ntl::RR g()
{
unsigned long p = ntl::RR::precision();
if(p <= 72)
return lanczos13UDT::g();
else if(p <= 120)
return lanczos22UDT::g();
else if(p <= 170)
return lanczos31UDT::g();
else //if(p <= 370) approx 100 digit precision:
return lanczos61UDT::g();
}
};
template<class Policy>
struct lanczos<ntl::RR, Policy>
{
typedef ntl_lanczos type;
};
} // namespace lanczos
namespace tools
{
template<>
inline int digits<boost::math::ntl::RR>(BOOST_MATH_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)
{
int result;
detail::convert_to_long_result(t.value(), result);
return result;
}
template <>
inline long real_cast<long, boost::math::ntl::RR>(boost::math::ntl::RR t)
{
long result;
detail::convert_to_long_result(t.value(), result);
return result;
}
template <>
inline long long real_cast<long long, boost::math::ntl::RR>(boost::math::ntl::RR t)
{
long long result;
detail::convert_to_long_result(t.value(), result);
return result;
}
template <>
inline boost::math::ntl::RR max_value<boost::math::ntl::RR>(BOOST_MATH_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_MATH_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_MATH_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_MATH_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_MATH_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_MATH_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_MATH_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){}
boost::math::tuple<RR, RR, RR> operator()(RR const& p)
{
RR f0 = sin(p);
RR f1 = cos(p);
RR f2 = -f0;
f0 -= t;
return boost::math::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){}
boost::math::tuple<RR, RR, RR> operator()(RR const& p)
{
RR f0 = cos(p);
RR f1 = -sin(p);
RR f2 = -f0;
f0 -= t;
return boost::math::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){}
boost::math::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 boost::math::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 atan2(RR y, RR x)
{
if(x > 0)
return atan(y / x);
if(x < 0)
{
return y < 0 ? atan(y / x) - boost::math::constants::pi<RR>() : atan(y / x) + boost::math::constants::pi<RR>();
}
return y < 0 ? -boost::math::constants::half_pi<RR>() : boost::math::constants::half_pi<RR>() ;
}
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;
}
template <class Policy>
inline int iround(RR const& x, const Policy& pol)
{
return tools::real_cast<int>(round(x, pol));
}
template <class Policy>
inline long lround(RR const& x, const Policy& pol)
{
return tools::real_cast<long>(round(x, pol));
}
template <class Policy>
inline long long llround(RR const& x, const Policy& pol)
{
return tools::real_cast<long long>(round(x, pol));
}
template <class Policy>
inline int itrunc(RR const& x, const Policy& pol)
{
return tools::real_cast<int>(trunc(x, pol));
}
template <class Policy>
inline long ltrunc(RR const& x, const Policy& pol)
{
return tools::real_cast<long>(trunc(x, pol));
}
template <class Policy>
inline long long lltrunc(RR const& x, const Policy& pol)
{
return tools::real_cast<long long>(trunc(x, pol));
}
} // namespace ntl
namespace detail{
template <class Policy>
ntl::RR digamma_imp(ntl::RR x, const mpl::int_<0>* , const Policy& pol)
{
//
// This handles reflection of negative arguments, and all our
// error handling, then forwards to the T-specific approximation.
//
BOOST_MATH_STD_USING // ADL of std functions.
ntl::RR result = 0;
//
// Check for negative arguments and use reflection:
//
if(x < 0)
{
// Reflect:
x = 1 - x;
// Argument reduction for tan:
ntl::RR remainder = x - floor(x);
// Shift to negative if > 0.5:
if(remainder > 0.5)
{
remainder -= 1;
}
//
// check for evaluation at a negative pole:
//
if(remainder == 0)
{
return policies::raise_pole_error<ntl::RR>("boost::math::digamma<%1%>(%1%)", 0, (1-x), pol);
}
result = constants::pi<ntl::RR>() / tan(constants::pi<ntl::RR>() * remainder);
}
result += big_digamma(x);
return result;
}
} // namespace detail
} // namespace math
} // namespace boost
#endif // BOOST_MATH_REAL_CONCEPT_HPP

View File

@@ -0,0 +1,16 @@
// Boost common_factor.hpp header file -------------------------------------//
// (C) Copyright Daryle Walker 2001-2002.
// 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)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_MATH_COMMON_FACTOR_HPP
#define BOOST_MATH_COMMON_FACTOR_HPP
#include <boost/math/common_factor_ct.hpp>
#include <boost/math/common_factor_rt.hpp>
#endif // BOOST_MATH_COMMON_FACTOR_HPP

View File

@@ -0,0 +1,97 @@
// Boost common_factor_ct.hpp header file ----------------------------------//
// (C) Copyright Daryle Walker and Stephen Cleary 2001-2002.
// 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)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_MATH_COMMON_FACTOR_CT_HPP
#define BOOST_MATH_COMMON_FACTOR_CT_HPP
#include <boost/math_fwd.hpp> // self include
#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT, etc.
#include <boost/mpl/integral_c.hpp>
namespace boost
{
namespace math
{
// Implementation details --------------------------------------------------//
namespace detail
{
// Build GCD with Euclid's recursive algorithm
template < static_gcd_type Value1, static_gcd_type Value2 >
struct static_gcd_helper_t
{
private:
BOOST_STATIC_CONSTANT( static_gcd_type, new_value1 = Value2 );
BOOST_STATIC_CONSTANT( static_gcd_type, new_value2 = Value1 % Value2 );
#ifndef __BORLANDC__
#define BOOST_DETAIL_GCD_HELPER_VAL(Value) static_cast<static_gcd_type>(Value)
#else
typedef static_gcd_helper_t self_type;
#define BOOST_DETAIL_GCD_HELPER_VAL(Value) (self_type:: Value )
#endif
typedef static_gcd_helper_t< BOOST_DETAIL_GCD_HELPER_VAL(new_value1),
BOOST_DETAIL_GCD_HELPER_VAL(new_value2) > next_step_type;
#undef BOOST_DETAIL_GCD_HELPER_VAL
public:
BOOST_STATIC_CONSTANT( static_gcd_type, value = next_step_type::value );
};
// Non-recursive case
template < static_gcd_type Value1 >
struct static_gcd_helper_t< Value1, 0UL >
{
BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 );
};
// Build the LCM from the GCD
template < static_gcd_type Value1, static_gcd_type Value2 >
struct static_lcm_helper_t
{
typedef static_gcd_helper_t<Value1, Value2> gcd_type;
BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 / gcd_type::value
* Value2 );
};
// Special case for zero-GCD values
template < >
struct static_lcm_helper_t< 0UL, 0UL >
{
BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL );
};
} // namespace detail
// Compile-time greatest common divisor evaluator class declaration --------//
template < static_gcd_type Value1, static_gcd_type Value2 >
struct static_gcd : public mpl::integral_c<static_gcd_type, (detail::static_gcd_helper_t<Value1, Value2>::value) >
{
}; // boost::math::static_gcd
// Compile-time least common multiple evaluator class declaration ----------//
template < static_gcd_type Value1, static_gcd_type Value2 >
struct static_lcm : public mpl::integral_c<static_gcd_type, (detail::static_lcm_helper_t<Value1, Value2>::value) >
{
}; // boost::math::static_lcm
} // namespace math
} // namespace boost
#endif // BOOST_MATH_COMMON_FACTOR_CT_HPP

View File

@@ -0,0 +1,428 @@
// (C) Copyright Jeremy William Murphy 2016.
// 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_COMMON_FACTOR_RT_HPP
#define BOOST_MATH_COMMON_FACTOR_RT_HPP
#include <boost/assert.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/type_traits.hpp>
#include <boost/config.hpp> // for BOOST_NESTED_TEMPLATE, etc.
#include <boost/limits.hpp> // for std::numeric_limits
#include <climits> // for CHAR_MIN
#include <boost/detail/workaround.hpp>
#include <iterator>
#include <algorithm>
#include <limits>
#if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
#include <intrin.h>
#endif
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127 4244) // Conditional expression is constant
#endif
namespace boost {
namespace math {
template <class T, bool a = is_unsigned<T>::value || (std::numeric_limits<T>::is_specialized && !std::numeric_limits<T>::is_signed)>
struct gcd_traits_abs_defaults
{
inline static const T& abs(const T& val) { return val; }
};
template <class T>
struct gcd_traits_abs_defaults<T, false>
{
inline static T abs(const T& val)
{
using std::abs;
return abs(val);
}
};
template <class T>
struct gcd_traits_defaults : public gcd_traits_abs_defaults<T>
{
BOOST_FORCEINLINE static unsigned make_odd(T& val)
{
unsigned r = 0;
while(!(val & 1u))
{
val >>= 1;
++r;
}
return r;
}
inline static bool less(const T& a, const T& b)
{
return a < b;
}
enum method_type
{
method_euclid = 0,
method_binary = 1,
method_mixed = 2,
};
static const method_type method =
boost::has_right_shift_assign<T>::value && boost::has_left_shift_assign<T>::value && boost::has_less<T>::value && boost::has_modulus<T>::value
? method_mixed :
boost::has_right_shift_assign<T>::value && boost::has_left_shift_assign<T>::value && boost::has_less<T>::value
? method_binary : method_euclid;
};
//
// Default gcd_traits just inherits from defaults:
//
template <class T>
struct gcd_traits : public gcd_traits_defaults<T> {};
//
// Special handling for polynomials:
//
namespace tools {
template <class T>
class polynomial;
}
template <class T>
struct gcd_traits<boost::math::tools::polynomial<T> > : public gcd_traits_defaults<T>
{
static const boost::math::tools::polynomial<T>& abs(const boost::math::tools::polynomial<T>& val) { return val; }
};
//
// Some platforms have fast bitscan operations, that allow us to implement
// make_odd much more efficiently:
//
#if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
#pragma intrinsic(_BitScanForward,)
template <>
struct gcd_traits<unsigned long> : public gcd_traits_defaults<unsigned long>
{
BOOST_FORCEINLINE static unsigned find_lsb(unsigned long val)
{
unsigned long result;
_BitScanForward(&result, val);
return result;
}
BOOST_FORCEINLINE static unsigned make_odd(unsigned long& val)
{
unsigned result = find_lsb(val);
val >>= result;
return result;
}
};
#ifdef _M_X64
#pragma intrinsic(_BitScanForward64)
template <>
struct gcd_traits<unsigned __int64> : public gcd_traits_defaults<unsigned __int64>
{
BOOST_FORCEINLINE static unsigned find_lsb(unsigned __int64 mask)
{
unsigned long result;
_BitScanForward64(&result, mask);
return result;
}
BOOST_FORCEINLINE static unsigned make_odd(unsigned __int64& val)
{
unsigned result = find_lsb(val);
val >>= result;
return result;
}
};
#endif
//
// Other integer type are trivial adaptations of the above,
// this works for signed types too, as by the time these functions
// are called, all values are > 0.
//
template <> struct gcd_traits<long> : public gcd_traits_defaults<long>
{ BOOST_FORCEINLINE static unsigned make_odd(long& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
template <> struct gcd_traits<unsigned int> : public gcd_traits_defaults<unsigned int>
{ BOOST_FORCEINLINE static unsigned make_odd(unsigned int& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
template <> struct gcd_traits<int> : public gcd_traits_defaults<int>
{ BOOST_FORCEINLINE static unsigned make_odd(int& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
template <> struct gcd_traits<unsigned short> : public gcd_traits_defaults<unsigned short>
{ BOOST_FORCEINLINE static unsigned make_odd(unsigned short& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
template <> struct gcd_traits<short> : public gcd_traits_defaults<short>
{ BOOST_FORCEINLINE static unsigned make_odd(short& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
template <> struct gcd_traits<unsigned char> : public gcd_traits_defaults<unsigned char>
{ BOOST_FORCEINLINE static unsigned make_odd(unsigned char& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
template <> struct gcd_traits<signed char> : public gcd_traits_defaults<signed char>
{ BOOST_FORCEINLINE static signed make_odd(signed char& val){ signed result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
template <> struct gcd_traits<char> : public gcd_traits_defaults<char>
{ BOOST_FORCEINLINE static unsigned make_odd(char& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
template <> struct gcd_traits<wchar_t> : public gcd_traits_defaults<wchar_t>
{ BOOST_FORCEINLINE static unsigned make_odd(wchar_t& val){ unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; } };
#ifdef _M_X64
template <> struct gcd_traits<__int64> : public gcd_traits_defaults<__int64>
{ BOOST_FORCEINLINE static unsigned make_odd(__int64& val){ unsigned result = gcd_traits<unsigned __int64>::find_lsb(val); val >>= result; return result; } };
#endif
#elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
template <>
struct gcd_traits<unsigned> : public gcd_traits_defaults<unsigned>
{
BOOST_FORCEINLINE static unsigned find_lsb(unsigned mask)
{
return __builtin_ctz(mask);
}
BOOST_FORCEINLINE static unsigned make_odd(unsigned& val)
{
unsigned result = find_lsb(val);
val >>= result;
return result;
}
};
template <>
struct gcd_traits<unsigned long> : public gcd_traits_defaults<unsigned long>
{
BOOST_FORCEINLINE static unsigned find_lsb(unsigned long mask)
{
return __builtin_ctzl(mask);
}
BOOST_FORCEINLINE static unsigned make_odd(unsigned long& val)
{
unsigned result = find_lsb(val);
val >>= result;
return result;
}
};
template <>
struct gcd_traits<boost::ulong_long_type> : public gcd_traits_defaults<boost::ulong_long_type>
{
BOOST_FORCEINLINE static unsigned find_lsb(boost::ulong_long_type mask)
{
return __builtin_ctzll(mask);
}
BOOST_FORCEINLINE static unsigned make_odd(boost::ulong_long_type& val)
{
unsigned result = find_lsb(val);
val >>= result;
return result;
}
};
//
// Other integer type are trivial adaptations of the above,
// this works for signed types too, as by the time these functions
// are called, all values are > 0.
//
template <> struct gcd_traits<boost::long_long_type> : public gcd_traits_defaults<boost::long_long_type>
{
BOOST_FORCEINLINE static unsigned make_odd(boost::long_long_type& val) { unsigned result = gcd_traits<boost::ulong_long_type>::find_lsb(val); val >>= result; return result; }
};
template <> struct gcd_traits<long> : public gcd_traits_defaults<long>
{
BOOST_FORCEINLINE static unsigned make_odd(long& val) { unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; }
};
template <> struct gcd_traits<int> : public gcd_traits_defaults<int>
{
BOOST_FORCEINLINE static unsigned make_odd(int& val) { unsigned result = gcd_traits<unsigned long>::find_lsb(val); val >>= result; return result; }
};
template <> struct gcd_traits<unsigned short> : public gcd_traits_defaults<unsigned short>
{
BOOST_FORCEINLINE static unsigned make_odd(unsigned short& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
};
template <> struct gcd_traits<short> : public gcd_traits_defaults<short>
{
BOOST_FORCEINLINE static unsigned make_odd(short& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
};
template <> struct gcd_traits<unsigned char> : public gcd_traits_defaults<unsigned char>
{
BOOST_FORCEINLINE static unsigned make_odd(unsigned char& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
};
template <> struct gcd_traits<signed char> : public gcd_traits_defaults<signed char>
{
BOOST_FORCEINLINE static signed make_odd(signed char& val) { signed result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
};
template <> struct gcd_traits<char> : public gcd_traits_defaults<char>
{
BOOST_FORCEINLINE static unsigned make_odd(char& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
};
template <> struct gcd_traits<wchar_t> : public gcd_traits_defaults<wchar_t>
{
BOOST_FORCEINLINE static unsigned make_odd(wchar_t& val) { unsigned result = gcd_traits<unsigned>::find_lsb(val); val >>= result; return result; }
};
#endif
namespace detail
{
//
// The Mixed Binary Euclid Algorithm
// Sidi Mohamed Sedjelmaci
// Electronic Notes in Discrete Mathematics 35 (2009) 169-176
//
template <class T>
T mixed_binary_gcd(T u, T v)
{
using std::swap;
if(gcd_traits<T>::less(u, v))
swap(u, v);
unsigned shifts = 0;
if(!u)
return v;
if(!v)
return u;
shifts = (std::min)(gcd_traits<T>::make_odd(u), gcd_traits<T>::make_odd(v));
while(gcd_traits<T>::less(1, v))
{
u %= v;
v -= u;
if(!u)
return v << shifts;
if(!v)
return u << shifts;
gcd_traits<T>::make_odd(u);
gcd_traits<T>::make_odd(v);
if(gcd_traits<T>::less(u, v))
swap(u, v);
}
return (v == 1 ? v : u) << shifts;
}
/** Stein gcd (aka 'binary gcd')
*
* From Mathematics to Generic Programming, Alexander Stepanov, Daniel Rose
*/
template <typename SteinDomain>
SteinDomain Stein_gcd(SteinDomain m, SteinDomain n)
{
using std::swap;
BOOST_ASSERT(m >= 0);
BOOST_ASSERT(n >= 0);
if (m == SteinDomain(0))
return n;
if (n == SteinDomain(0))
return m;
// m > 0 && n > 0
int d_m = gcd_traits<SteinDomain>::make_odd(m);
int d_n = gcd_traits<SteinDomain>::make_odd(n);
// odd(m) && odd(n)
while (m != n)
{
if (n > m)
swap(n, m);
m -= n;
gcd_traits<SteinDomain>::make_odd(m);
}
// m == n
m <<= (std::min)(d_m, d_n);
return m;
}
/** Euclidean algorithm
*
* From Mathematics to Generic Programming, Alexander Stepanov, Daniel Rose
*
*/
template <typename EuclideanDomain>
inline EuclideanDomain Euclid_gcd(EuclideanDomain a, EuclideanDomain b)
{
using std::swap;
while (b != EuclideanDomain(0))
{
a %= b;
swap(a, b);
}
return a;
}
template <typename T>
inline BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == gcd_traits<T>::method_mixed, T>::type
optimal_gcd_select(T const &a, T const &b)
{
return detail::mixed_binary_gcd(a, b);
}
template <typename T>
inline BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == gcd_traits<T>::method_binary, T>::type
optimal_gcd_select(T const &a, T const &b)
{
return detail::Stein_gcd(a, b);
}
template <typename T>
inline BOOST_DEDUCED_TYPENAME enable_if_c<gcd_traits<T>::method == gcd_traits<T>::method_euclid, T>::type
optimal_gcd_select(T const &a, T const &b)
{
return detail::Euclid_gcd(a, b);
}
template <class T>
inline T lcm_imp(const T& a, const T& b)
{
T temp = boost::math::detail::optimal_gcd_select(a, b);
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500)
return (temp != T(0)) ? T(a / temp * b) : T(0);
#else
return temp ? T(a / temp * b) : T(0);
#endif
}
} // namespace detail
template <typename Integer>
inline Integer gcd(Integer const &a, Integer const &b)
{
return detail::optimal_gcd_select(static_cast<Integer>(gcd_traits<Integer>::abs(a)), static_cast<Integer>(gcd_traits<Integer>::abs(b)));
}
template <typename Integer>
inline Integer lcm(Integer const &a, Integer const &b)
{
return detail::lcm_imp(static_cast<Integer>(gcd_traits<Integer>::abs(a)), static_cast<Integer>(gcd_traits<Integer>::abs(b)));
}
/**
* Knuth, The Art of Computer Programming: Volume 2, Third edition, 1998
* Chapter 4.5.2, Algorithm C: Greatest common divisor of n integers.
*
* Knuth counts down from n to zero but we naturally go from first to last.
* We also return the termination position because it might be useful to know.
*
* Partly by quirk, partly by design, this algorithm is defined for n = 1,
* because the gcd of {x} is x. It is not defined for n = 0.
*
* @tparam I Input iterator.
* @return The gcd of the range and the iterator position at termination.
*/
template <typename I>
std::pair<typename std::iterator_traits<I>::value_type, I>
gcd_range(I first, I last)
{
BOOST_ASSERT(first != last);
typedef typename std::iterator_traits<I>::value_type T;
T d = *first++;
while (d != T(1) && first != last)
{
d = gcd(d, *first);
first++;
}
return std::make_pair(d, first);
}
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#endif // BOOST_MATH_COMMON_FACTOR_RT_HPP

View File

@@ -0,0 +1,32 @@
// (C) Copyright John Maddock 2005.
// 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_COMPLEX_INCLUDED
#define BOOST_MATH_COMPLEX_INCLUDED
#ifndef BOOST_MATH_COMPLEX_ASIN_INCLUDED
# include <boost/math/complex/asin.hpp>
#endif
#ifndef BOOST_MATH_COMPLEX_ASINH_INCLUDED
# include <boost/math/complex/asinh.hpp>
#endif
#ifndef BOOST_MATH_COMPLEX_ACOS_INCLUDED
# include <boost/math/complex/acos.hpp>
#endif
#ifndef BOOST_MATH_COMPLEX_ACOSH_INCLUDED
# include <boost/math/complex/acosh.hpp>
#endif
#ifndef BOOST_MATH_COMPLEX_ATAN_INCLUDED
# include <boost/math/complex/atan.hpp>
#endif
#ifndef BOOST_MATH_COMPLEX_ATANH_INCLUDED
# include <boost/math/complex/atanh.hpp>
#endif
#ifndef BOOST_MATH_COMPLEX_FABS_INCLUDED
# include <boost/math/complex/fabs.hpp>
#endif
#endif // BOOST_MATH_COMPLEX_INCLUDED

View File

@@ -0,0 +1,245 @@
// (C) Copyright John Maddock 2005.
// 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)
#ifndef BOOST_MATH_COMPLEX_ACOS_INCLUDED
#define BOOST_MATH_COMPLEX_ACOS_INCLUDED
#ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED
# include <boost/math/complex/details.hpp>
#endif
#ifndef BOOST_MATH_LOG1P_INCLUDED
# include <boost/math/special_functions/log1p.hpp>
#endif
#include <boost/assert.hpp>
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std{ using ::sqrt; using ::fabs; using ::acos; using ::asin; using ::atan; using ::atan2; }
#endif
namespace boost{ namespace math{
template<class T>
std::complex<T> acos(const std::complex<T>& z)
{
//
// This implementation is a transcription of the pseudo-code in:
//
// "Implementing the Complex Arcsine and Arccosine Functions using Exception Handling."
// T E Hull, Thomas F Fairgrieve and Ping Tak Peter Tang.
// ACM Transactions on Mathematical Software, Vol 23, No 3, Sept 1997.
//
//
// These static constants should really be in a maths constants library,
// note that we have tweaked a_crossover as per: https://svn.boost.org/trac/boost/ticket/7290
//
static const T one = static_cast<T>(1);
//static const T two = static_cast<T>(2);
static const T half = static_cast<T>(0.5L);
static const T a_crossover = static_cast<T>(10);
static const T b_crossover = static_cast<T>(0.6417L);
static const T s_pi = boost::math::constants::pi<T>();
static const T half_pi = s_pi / 2;
static const T log_two = boost::math::constants::ln_two<T>();
static const T quarter_pi = s_pi / 4;
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127)
#endif
//
// Get real and imaginary parts, discard the signs as we can
// figure out the sign of the result later:
//
T x = std::fabs(z.real());
T y = std::fabs(z.imag());
T real, imag; // these hold our result
//
// Handle special cases specified by the C99 standard,
// many of these special cases aren't really needed here,
// but doing it this way prevents overflow/underflow arithmetic
// in the main body of the logic, which may trip up some machines:
//
if((boost::math::isinf)(x))
{
if((boost::math::isinf)(y))
{
real = quarter_pi;
imag = std::numeric_limits<T>::infinity();
}
else if((boost::math::isnan)(y))
{
return std::complex<T>(y, -std::numeric_limits<T>::infinity());
}
else
{
// y is not infinity or nan:
real = 0;
imag = std::numeric_limits<T>::infinity();
}
}
else if((boost::math::isnan)(x))
{
if((boost::math::isinf)(y))
return std::complex<T>(x, ((boost::math::signbit)(z.imag())) ? std::numeric_limits<T>::infinity() : -std::numeric_limits<T>::infinity());
return std::complex<T>(x, x);
}
else if((boost::math::isinf)(y))
{
real = half_pi;
imag = std::numeric_limits<T>::infinity();
}
else if((boost::math::isnan)(y))
{
return std::complex<T>((x == 0) ? half_pi : y, y);
}
else
{
//
// What follows is the regular Hull et al code,
// begin with the special case for real numbers:
//
if((y == 0) && (x <= one))
return std::complex<T>((x == 0) ? half_pi : std::acos(z.real()), (boost::math::changesign)(z.imag()));
//
// Figure out if our input is within the "safe area" identified by Hull et al.
// This would be more efficient with portable floating point exception handling;
// fortunately the quantities M and u identified by Hull et al (figure 3),
// match with the max and min methods of numeric_limits<T>.
//
T safe_max = detail::safe_max(static_cast<T>(8));
T safe_min = detail::safe_min(static_cast<T>(4));
T xp1 = one + x;
T xm1 = x - one;
if((x < safe_max) && (x > safe_min) && (y < safe_max) && (y > safe_min))
{
T yy = y * y;
T r = std::sqrt(xp1*xp1 + yy);
T s = std::sqrt(xm1*xm1 + yy);
T a = half * (r + s);
T b = x / a;
if(b <= b_crossover)
{
real = std::acos(b);
}
else
{
T apx = a + x;
if(x <= one)
{
real = std::atan(std::sqrt(half * apx * (yy /(r + xp1) + (s-xm1)))/x);
}
else
{
real = std::atan((y * std::sqrt(half * (apx/(r + xp1) + apx/(s+xm1))))/x);
}
}
if(a <= a_crossover)
{
T am1;
if(x < one)
{
am1 = half * (yy/(r + xp1) + yy/(s - xm1));
}
else
{
am1 = half * (yy/(r + xp1) + (s + xm1));
}
imag = boost::math::log1p(am1 + std::sqrt(am1 * (a + one)));
}
else
{
imag = std::log(a + std::sqrt(a*a - one));
}
}
else
{
//
// This is the Hull et al exception handling code from Fig 6 of their paper:
//
if(y <= (std::numeric_limits<T>::epsilon() * std::fabs(xm1)))
{
if(x < one)
{
real = std::acos(x);
imag = y / std::sqrt(xp1*(one-x));
}
else
{
// This deviates from Hull et al's paper as per https://svn.boost.org/trac/boost/ticket/7290
if(((std::numeric_limits<T>::max)() / xp1) > xm1)
{
// xp1 * xm1 won't overflow:
real = y / std::sqrt(xm1*xp1);
imag = boost::math::log1p(xm1 + std::sqrt(xp1*xm1));
}
else
{
real = y / x;
imag = log_two + std::log(x);
}
}
}
else if(y <= safe_min)
{
// There is an assumption in Hull et al's analysis that
// if we get here then x == 1. This is true for all "good"
// machines where :
//
// E^2 > 8*sqrt(u); with:
//
// E = std::numeric_limits<T>::epsilon()
// u = (std::numeric_limits<T>::min)()
//
// Hull et al provide alternative code for "bad" machines
// but we have no way to test that here, so for now just assert
// on the assumption:
//
BOOST_ASSERT(x == 1);
real = std::sqrt(y);
imag = std::sqrt(y);
}
else if(std::numeric_limits<T>::epsilon() * y - one >= x)
{
real = half_pi;
imag = log_two + std::log(y);
}
else if(x > one)
{
real = std::atan(y/x);
T xoy = x/y;
imag = log_two + std::log(y) + half * boost::math::log1p(xoy*xoy);
}
else
{
real = half_pi;
T a = std::sqrt(one + y*y);
imag = half * boost::math::log1p(static_cast<T>(2)*y*(y+a));
}
}
}
//
// Finish off by working out the sign of the result:
//
if((boost::math::signbit)(z.real()))
real = s_pi - real;
if(!(boost::math::signbit)(z.imag()))
imag = (boost::math::changesign)(imag);
return std::complex<T>(real, imag);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
} } // namespaces
#endif // BOOST_MATH_COMPLEX_ACOS_INCLUDED

View File

@@ -0,0 +1,34 @@
// (C) Copyright John Maddock 2005.
// 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_COMPLEX_ACOSH_INCLUDED
#define BOOST_MATH_COMPLEX_ACOSH_INCLUDED
#ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED
# include <boost/math/complex/details.hpp>
#endif
#ifndef BOOST_MATH_COMPLEX_ATANH_INCLUDED
# include <boost/math/complex/acos.hpp>
#endif
namespace boost{ namespace math{
template<class T>
inline std::complex<T> acosh(const std::complex<T>& z)
{
//
// We use the relation acosh(z) = +-i acos(z)
// Choosing the sign of multiplier to give real(acosh(z)) >= 0
// as well as compatibility with C99.
//
std::complex<T> result = boost::math::acos(z);
if(!(boost::math::isnan)(result.imag()) && signbit(result.imag()))
return detail::mult_i(result);
return detail::mult_minus_i(result);
}
} } // namespaces
#endif // BOOST_MATH_COMPLEX_ACOSH_INCLUDED

View File

@@ -0,0 +1,252 @@
// (C) Copyright John Maddock 2005.
// 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)
#ifndef BOOST_MATH_COMPLEX_ASIN_INCLUDED
#define BOOST_MATH_COMPLEX_ASIN_INCLUDED
#ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED
# include <boost/math/complex/details.hpp>
#endif
#ifndef BOOST_MATH_LOG1P_INCLUDED
# include <boost/math/special_functions/log1p.hpp>
#endif
#include <boost/assert.hpp>
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std{ using ::sqrt; using ::fabs; using ::acos; using ::asin; using ::atan; using ::atan2; }
#endif
namespace boost{ namespace math{
template<class T>
inline std::complex<T> asin(const std::complex<T>& z)
{
//
// This implementation is a transcription of the pseudo-code in:
//
// "Implementing the complex Arcsine and Arccosine Functions using Exception Handling."
// T E Hull, Thomas F Fairgrieve and Ping Tak Peter Tang.
// ACM Transactions on Mathematical Software, Vol 23, No 3, Sept 1997.
//
//
// These static constants should really be in a maths constants library,
// note that we have tweaked the value of a_crossover as per https://svn.boost.org/trac/boost/ticket/7290:
//
static const T one = static_cast<T>(1);
//static const T two = static_cast<T>(2);
static const T half = static_cast<T>(0.5L);
static const T a_crossover = static_cast<T>(10);
static const T b_crossover = static_cast<T>(0.6417L);
static const T s_pi = boost::math::constants::pi<T>();
static const T half_pi = s_pi / 2;
static const T log_two = boost::math::constants::ln_two<T>();
static const T quarter_pi = s_pi / 4;
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127)
#endif
//
// Get real and imaginary parts, discard the signs as we can
// figure out the sign of the result later:
//
T x = std::fabs(z.real());
T y = std::fabs(z.imag());
T real, imag; // our results
//
// Begin by handling the special cases for infinities and nan's
// specified in C99, most of this is handled by the regular logic
// below, but handling it as a special case prevents overflow/underflow
// arithmetic which may trip up some machines:
//
if((boost::math::isnan)(x))
{
if((boost::math::isnan)(y))
return std::complex<T>(x, x);
if((boost::math::isinf)(y))
{
real = x;
imag = std::numeric_limits<T>::infinity();
}
else
return std::complex<T>(x, x);
}
else if((boost::math::isnan)(y))
{
if(x == 0)
{
real = 0;
imag = y;
}
else if((boost::math::isinf)(x))
{
real = y;
imag = std::numeric_limits<T>::infinity();
}
else
return std::complex<T>(y, y);
}
else if((boost::math::isinf)(x))
{
if((boost::math::isinf)(y))
{
real = quarter_pi;
imag = std::numeric_limits<T>::infinity();
}
else
{
real = half_pi;
imag = std::numeric_limits<T>::infinity();
}
}
else if((boost::math::isinf)(y))
{
real = 0;
imag = std::numeric_limits<T>::infinity();
}
else
{
//
// special case for real numbers:
//
if((y == 0) && (x <= one))
return std::complex<T>(std::asin(z.real()), z.imag());
//
// Figure out if our input is within the "safe area" identified by Hull et al.
// This would be more efficient with portable floating point exception handling;
// fortunately the quantities M and u identified by Hull et al (figure 3),
// match with the max and min methods of numeric_limits<T>.
//
T safe_max = detail::safe_max(static_cast<T>(8));
T safe_min = detail::safe_min(static_cast<T>(4));
T xp1 = one + x;
T xm1 = x - one;
if((x < safe_max) && (x > safe_min) && (y < safe_max) && (y > safe_min))
{
T yy = y * y;
T r = std::sqrt(xp1*xp1 + yy);
T s = std::sqrt(xm1*xm1 + yy);
T a = half * (r + s);
T b = x / a;
if(b <= b_crossover)
{
real = std::asin(b);
}
else
{
T apx = a + x;
if(x <= one)
{
real = std::atan(x/std::sqrt(half * apx * (yy /(r + xp1) + (s-xm1))));
}
else
{
real = std::atan(x/(y * std::sqrt(half * (apx/(r + xp1) + apx/(s+xm1)))));
}
}
if(a <= a_crossover)
{
T am1;
if(x < one)
{
am1 = half * (yy/(r + xp1) + yy/(s - xm1));
}
else
{
am1 = half * (yy/(r + xp1) + (s + xm1));
}
imag = boost::math::log1p(am1 + std::sqrt(am1 * (a + one)));
}
else
{
imag = std::log(a + std::sqrt(a*a - one));
}
}
else
{
//
// This is the Hull et al exception handling code from Fig 3 of their paper:
//
if(y <= (std::numeric_limits<T>::epsilon() * std::fabs(xm1)))
{
if(x < one)
{
real = std::asin(x);
imag = y / std::sqrt(-xp1*xm1);
}
else
{
real = half_pi;
if(((std::numeric_limits<T>::max)() / xp1) > xm1)
{
// xp1 * xm1 won't overflow:
imag = boost::math::log1p(xm1 + std::sqrt(xp1*xm1));
}
else
{
imag = log_two + std::log(x);
}
}
}
else if(y <= safe_min)
{
// There is an assumption in Hull et al's analysis that
// if we get here then x == 1. This is true for all "good"
// machines where :
//
// E^2 > 8*sqrt(u); with:
//
// E = std::numeric_limits<T>::epsilon()
// u = (std::numeric_limits<T>::min)()
//
// Hull et al provide alternative code for "bad" machines
// but we have no way to test that here, so for now just assert
// on the assumption:
//
BOOST_ASSERT(x == 1);
real = half_pi - std::sqrt(y);
imag = std::sqrt(y);
}
else if(std::numeric_limits<T>::epsilon() * y - one >= x)
{
real = x/y; // This can underflow!
imag = log_two + std::log(y);
}
else if(x > one)
{
real = std::atan(x/y);
T xoy = x/y;
imag = log_two + std::log(y) + half * boost::math::log1p(xoy*xoy);
}
else
{
T a = std::sqrt(one + y*y);
real = x/a; // This can underflow!
imag = half * boost::math::log1p(static_cast<T>(2)*y*(y+a));
}
}
}
//
// Finish off by working out the sign of the result:
//
if((boost::math::signbit)(z.real()))
real = (boost::math::changesign)(real);
if((boost::math::signbit)(z.imag()))
imag = (boost::math::changesign)(imag);
return std::complex<T>(real, imag);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
} } // namespaces
#endif // BOOST_MATH_COMPLEX_ASIN_INCLUDED

View File

@@ -0,0 +1,32 @@
// (C) Copyright John Maddock 2005.
// 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_COMPLEX_ASINH_INCLUDED
#define BOOST_MATH_COMPLEX_ASINH_INCLUDED
#ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED
# include <boost/math/complex/details.hpp>
#endif
#ifndef BOOST_MATH_COMPLEX_ASIN_INCLUDED
# include <boost/math/complex/asin.hpp>
#endif
namespace boost{ namespace math{
template<class T>
inline std::complex<T> asinh(const std::complex<T>& x)
{
//
// We use asinh(z) = i asin(-i z);
// Note that C99 defines this the other way around (which is
// to say asin is specified in terms of asinh), this is consistent
// with C99 though:
//
return ::boost::math::detail::mult_i(::boost::math::asin(::boost::math::detail::mult_minus_i(x)));
}
} } // namespaces
#endif // BOOST_MATH_COMPLEX_ASINH_INCLUDED

View File

@@ -0,0 +1,36 @@
// (C) Copyright John Maddock 2005.
// 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_COMPLEX_ATAN_INCLUDED
#define BOOST_MATH_COMPLEX_ATAN_INCLUDED
#ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED
# include <boost/math/complex/details.hpp>
#endif
#ifndef BOOST_MATH_COMPLEX_ATANH_INCLUDED
# include <boost/math/complex/atanh.hpp>
#endif
namespace boost{ namespace math{
template<class T>
std::complex<T> atan(const std::complex<T>& x)
{
//
// We're using the C99 definition here; atan(z) = -i atanh(iz):
//
if(x.real() == 0)
{
if(x.imag() == 1)
return std::complex<T>(0, std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : static_cast<T>(HUGE_VAL));
if(x.imag() == -1)
return std::complex<T>(0, std::numeric_limits<T>::has_infinity ? -std::numeric_limits<T>::infinity() : -static_cast<T>(HUGE_VAL));
}
return ::boost::math::detail::mult_minus_i(::boost::math::atanh(::boost::math::detail::mult_i(x)));
}
} } // namespaces
#endif // BOOST_MATH_COMPLEX_ATAN_INCLUDED

View File

@@ -0,0 +1,214 @@
// (C) Copyright John Maddock 2005.
// 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_COMPLEX_ATANH_INCLUDED
#define BOOST_MATH_COMPLEX_ATANH_INCLUDED
#ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED
# include <boost/math/complex/details.hpp>
#endif
#ifndef BOOST_MATH_LOG1P_INCLUDED
# include <boost/math/special_functions/log1p.hpp>
#endif
#include <boost/assert.hpp>
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std{ using ::sqrt; using ::fabs; using ::acos; using ::asin; using ::atan; using ::atan2; }
#endif
namespace boost{ namespace math{
template<class T>
std::complex<T> atanh(const std::complex<T>& z)
{
//
// References:
//
// Eric W. Weisstein. "Inverse Hyperbolic Tangent."
// From MathWorld--A Wolfram Web Resource.
// http://mathworld.wolfram.com/InverseHyperbolicTangent.html
//
// Also: The Wolfram Functions Site,
// http://functions.wolfram.com/ElementaryFunctions/ArcTanh/
//
// Also "Abramowitz and Stegun. Handbook of Mathematical Functions."
// at : http://jove.prohosting.com/~skripty/toc.htm
//
// See also: https://svn.boost.org/trac/boost/ticket/7291
//
static const T pi = boost::math::constants::pi<T>();
static const T half_pi = pi / 2;
static const T one = static_cast<T>(1.0L);
static const T two = static_cast<T>(2.0L);
static const T four = static_cast<T>(4.0L);
static const T zero = static_cast<T>(0);
static const T log_two = boost::math::constants::ln_two<T>();
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127)
#endif
T x = std::fabs(z.real());
T y = std::fabs(z.imag());
T real, imag; // our results
T safe_upper = detail::safe_max(two);
T safe_lower = detail::safe_min(static_cast<T>(2));
//
// Begin by handling the special cases specified in C99:
//
if((boost::math::isnan)(x))
{
if((boost::math::isnan)(y))
return std::complex<T>(x, x);
else if((boost::math::isinf)(y))
return std::complex<T>(0, ((boost::math::signbit)(z.imag()) ? -half_pi : half_pi));
else
return std::complex<T>(x, x);
}
else if((boost::math::isnan)(y))
{
if(x == 0)
return std::complex<T>(x, y);
if((boost::math::isinf)(x))
return std::complex<T>(0, y);
else
return std::complex<T>(y, y);
}
else if((x > safe_lower) && (x < safe_upper) && (y > safe_lower) && (y < safe_upper))
{
T yy = y*y;
T mxm1 = one - x;
///
// The real part is given by:
//
// real(atanh(z)) == log1p(4*x / ((x-1)*(x-1) + y^2))
//
real = boost::math::log1p(four * x / (mxm1*mxm1 + yy));
real /= four;
if((boost::math::signbit)(z.real()))
real = (boost::math::changesign)(real);
imag = std::atan2((y * two), (mxm1*(one+x) - yy));
imag /= two;
if(z.imag() < 0)
imag = (boost::math::changesign)(imag);
}
else
{
//
// This section handles exception cases that would normally cause
// underflow or overflow in the main formulas.
//
// Begin by working out the real part, we need to approximate
// real = boost::math::log1p(4x / ((x-1)^2 + y^2))
// without either overflow or underflow in the squared terms.
//
T mxm1 = one - x;
if(x >= safe_upper)
{
// x-1 = x to machine precision:
if((boost::math::isinf)(x) || (boost::math::isinf)(y))
{
real = 0;
}
else if(y >= safe_upper)
{
// Big x and y: divide through by x*y:
real = boost::math::log1p((four/y) / (x/y + y/x));
}
else if(y > one)
{
// Big x: divide through by x:
real = boost::math::log1p(four / (x + y*y/x));
}
else
{
// Big x small y, as above but neglect y^2/x:
real = boost::math::log1p(four/x);
}
}
else if(y >= safe_upper)
{
if(x > one)
{
// Big y, medium x, divide through by y:
real = boost::math::log1p((four*x/y) / (y + mxm1*mxm1/y));
}
else
{
// Small or medium x, large y:
real = four*x/y/y;
}
}
else if (x != one)
{
// y is small, calculate divisor carefully:
T div = mxm1*mxm1;
if(y > safe_lower)
div += y*y;
real = boost::math::log1p(four*x/div);
}
else
real = boost::math::changesign(two * (std::log(y) - log_two));
real /= four;
if((boost::math::signbit)(z.real()))
real = (boost::math::changesign)(real);
//
// Now handle imaginary part, this is much easier,
// if x or y are large, then the formula:
// atan2(2y, (1-x)*(1+x) - y^2)
// evaluates to +-(PI - theta) where theta is negligible compared to PI.
//
if((x >= safe_upper) || (y >= safe_upper))
{
imag = pi;
}
else if(x <= safe_lower)
{
//
// If both x and y are small then atan(2y),
// otherwise just x^2 is negligible in the divisor:
//
if(y <= safe_lower)
imag = std::atan2(two*y, one);
else
{
if((y == zero) && (x == zero))
imag = 0;
else
imag = std::atan2(two*y, one - y*y);
}
}
else
{
//
// y^2 is negligible:
//
if((y == zero) && (x == one))
imag = 0;
else
imag = std::atan2(two*y, mxm1*(one+x));
}
imag /= two;
if((boost::math::signbit)(z.imag()))
imag = (boost::math::changesign)(imag);
}
return std::complex<T>(real, imag);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
} } // namespaces
#endif // BOOST_MATH_COMPLEX_ATANH_INCLUDED

View File

@@ -0,0 +1,96 @@
// (C) Copyright John Maddock 2005.
// 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_COMPLEX_DETAILS_INCLUDED
#define BOOST_MATH_COMPLEX_DETAILS_INCLUDED
//
// This header contains all the support code that is common to the
// inverse trig complex functions, it also contains all the includes
// that we need to implement all these functions.
//
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/config/no_tr1/complex.hpp>
#include <boost/limits.hpp>
#include <math.h> // isnan where available
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/math/special_functions/sign.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/special_functions/sign.hpp>
#include <boost/math/constants/constants.hpp>
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std{ using ::sqrt; }
#endif
namespace boost{ namespace math{ namespace detail{
template <class T>
inline T mult_minus_one(const T& t)
{
return (boost::math::isnan)(t) ? t : (boost::math::changesign)(t);
}
template <class T>
inline std::complex<T> mult_i(const std::complex<T>& t)
{
return std::complex<T>(mult_minus_one(t.imag()), t.real());
}
template <class T>
inline std::complex<T> mult_minus_i(const std::complex<T>& t)
{
return std::complex<T>(t.imag(), mult_minus_one(t.real()));
}
template <class T>
inline T safe_max(T t)
{
return std::sqrt((std::numeric_limits<T>::max)()) / t;
}
inline long double safe_max(long double t)
{
// long double sqrt often returns infinity due to
// insufficient internal precision:
return std::sqrt((std::numeric_limits<double>::max)()) / t;
}
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
// workaround for type deduction bug:
inline float safe_max(float t)
{
return std::sqrt((std::numeric_limits<float>::max)()) / t;
}
inline double safe_max(double t)
{
return std::sqrt((std::numeric_limits<double>::max)()) / t;
}
#endif
template <class T>
inline T safe_min(T t)
{
return std::sqrt((std::numeric_limits<T>::min)()) * t;
}
inline long double safe_min(long double t)
{
// long double sqrt often returns zero due to
// insufficient internal precision:
return std::sqrt((std::numeric_limits<double>::min)()) * t;
}
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
// type deduction workaround:
inline double safe_min(double t)
{
return std::sqrt((std::numeric_limits<double>::min)()) * t;
}
inline float safe_min(float t)
{
return std::sqrt((std::numeric_limits<float>::min)()) * t;
}
#endif
} } } // namespaces
#endif // BOOST_MATH_COMPLEX_DETAILS_INCLUDED

View File

@@ -0,0 +1,23 @@
// (C) Copyright John Maddock 2005.
// 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_COMPLEX_FABS_INCLUDED
#define BOOST_MATH_COMPLEX_FABS_INCLUDED
#ifndef BOOST_MATH_HYPOT_INCLUDED
# include <boost/math/special_functions/hypot.hpp>
#endif
namespace boost{ namespace math{
template<class T>
inline T fabs(const std::complex<T>& z)
{
return ::boost::math::hypot(z.real(), z.imag());
}
} } // namespaces
#endif // BOOST_MATH_COMPLEX_FABS_INCLUDED

View File

@@ -0,0 +1,491 @@
// 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>
#include <boost/math/distributions/fwd.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4100)
#pragma warning(disable: 4510)
#pragma warning(disable: 4610)
#pragma warning(disable: 4189) // local variable is initialized but not referenced.
#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
{
typedef typename Distribution::value_type value_type;
void constraints()
{
function_requires<CopyConstructibleConcept<Distribution> >();
function_requires<AssignableConcept<Distribution> >();
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));
suppress_unused_variable_warning(v);
v = pdf(dist, x);
suppress_unused_variable_warning(v);
v = quantile(dist, x);
suppress_unused_variable_warning(v);
v = quantile(complement(dist, x));
suppress_unused_variable_warning(v);
v = mean(dist);
suppress_unused_variable_warning(v);
v = mode(dist);
suppress_unused_variable_warning(v);
v = standard_deviation(dist);
suppress_unused_variable_warning(v);
v = variance(dist);
suppress_unused_variable_warning(v);
v = hazard(dist, x);
suppress_unused_variable_warning(v);
v = chf(dist, x);
suppress_unused_variable_warning(v);
v = coefficient_of_variation(dist);
suppress_unused_variable_warning(v);
v = skewness(dist);
suppress_unused_variable_warning(v);
v = kurtosis(dist);
suppress_unused_variable_warning(v);
v = kurtosis_excess(dist);
suppress_unused_variable_warning(v);
v = median(dist);
suppress_unused_variable_warning(v);
std::pair<value_type, value_type> pv;
pv = range(dist);
suppress_unused_variable_warning(pv);
pv = support(dist);
suppress_unused_variable_warning(pv);
float f = 1;
v = cdf(dist, f);
suppress_unused_variable_warning(v);
v = cdf(complement(dist, f));
suppress_unused_variable_warning(v);
v = pdf(dist, f);
suppress_unused_variable_warning(v);
v = quantile(dist, f);
suppress_unused_variable_warning(v);
v = quantile(complement(dist, f));
suppress_unused_variable_warning(v);
v = hazard(dist, f);
suppress_unused_variable_warning(v);
v = chf(dist, f);
suppress_unused_variable_warning(v);
double d = 1;
v = cdf(dist, d);
suppress_unused_variable_warning(v);
v = cdf(complement(dist, d));
suppress_unused_variable_warning(v);
v = pdf(dist, d);
suppress_unused_variable_warning(v);
v = quantile(dist, d);
suppress_unused_variable_warning(v);
v = quantile(complement(dist, d));
suppress_unused_variable_warning(v);
v = hazard(dist, d);
suppress_unused_variable_warning(v);
v = chf(dist, d);
suppress_unused_variable_warning(v);
#ifndef TEST_MPFR
long double ld = 1;
v = cdf(dist, ld);
suppress_unused_variable_warning(v);
v = cdf(complement(dist, ld));
suppress_unused_variable_warning(v);
v = pdf(dist, ld);
suppress_unused_variable_warning(v);
v = quantile(dist, ld);
suppress_unused_variable_warning(v);
v = quantile(complement(dist, ld));
suppress_unused_variable_warning(v);
v = hazard(dist, ld);
suppress_unused_variable_warning(v);
v = chf(dist, ld);
suppress_unused_variable_warning(v);
#endif
int i = 1;
v = cdf(dist, i);
suppress_unused_variable_warning(v);
v = cdf(complement(dist, i));
suppress_unused_variable_warning(v);
v = pdf(dist, i);
suppress_unused_variable_warning(v);
v = quantile(dist, i);
suppress_unused_variable_warning(v);
v = quantile(complement(dist, i));
suppress_unused_variable_warning(v);
v = hazard(dist, i);
suppress_unused_variable_warning(v);
v = chf(dist, i);
suppress_unused_variable_warning(v);
unsigned long li = 1;
v = cdf(dist, li);
suppress_unused_variable_warning(v);
v = cdf(complement(dist, li));
suppress_unused_variable_warning(v);
v = pdf(dist, li);
suppress_unused_variable_warning(v);
v = quantile(dist, li);
suppress_unused_variable_warning(v);
v = quantile(complement(dist, li));
suppress_unused_variable_warning(v);
v = hazard(dist, li);
suppress_unused_variable_warning(v);
v = chf(dist, li);
suppress_unused_variable_warning(v);
test_extra_members(dist);
}
template <class D>
static void test_extra_members(const D&)
{}
template <class R, class P>
static void test_extra_members(const boost::math::bernoulli_distribution<R, P>& d)
{
value_type r = d.success_fraction();
(void)r; // warning suppression
}
template <class R, class P>
static void test_extra_members(const boost::math::beta_distribution<R, P>& d)
{
value_type r1 = d.alpha();
value_type r2 = d.beta();
r1 = boost::math::beta_distribution<R, P>::find_alpha(r1, r2);
suppress_unused_variable_warning(r1);
r1 = boost::math::beta_distribution<R, P>::find_beta(r1, r2);
suppress_unused_variable_warning(r1);
r1 = boost::math::beta_distribution<R, P>::find_alpha(r1, r2, r1);
suppress_unused_variable_warning(r1);
r1 = boost::math::beta_distribution<R, P>::find_beta(r1, r2, r1);
suppress_unused_variable_warning(r1);
}
template <class R, class P>
static void test_extra_members(const boost::math::binomial_distribution<R, P>& d)
{
value_type r = d.success_fraction();
r = d.trials();
r = Distribution::find_lower_bound_on_p(r, r, r);
r = Distribution::find_lower_bound_on_p(r, r, r, Distribution::clopper_pearson_exact_interval);
r = Distribution::find_lower_bound_on_p(r, r, r, Distribution::jeffreys_prior_interval);
r = Distribution::find_upper_bound_on_p(r, r, r);
r = Distribution::find_upper_bound_on_p(r, r, r, Distribution::clopper_pearson_exact_interval);
r = Distribution::find_upper_bound_on_p(r, r, r, Distribution::jeffreys_prior_interval);
r = Distribution::find_minimum_number_of_trials(r, r, r);
r = Distribution::find_maximum_number_of_trials(r, r, r);
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::cauchy_distribution<R, P>& d)
{
value_type r = d.location();
r = d.scale();
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::chi_squared_distribution<R, P>& d)
{
value_type r = d.degrees_of_freedom();
r = Distribution::find_degrees_of_freedom(r, r, r, r);
r = Distribution::find_degrees_of_freedom(r, r, r, r, r);
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::exponential_distribution<R, P>& d)
{
value_type r = d.lambda();
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::extreme_value_distribution<R, P>& d)
{
value_type r = d.scale();
r = d.location();
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::fisher_f_distribution<R, P>& d)
{
value_type r = d.degrees_of_freedom1();
r = d.degrees_of_freedom2();
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::gamma_distribution<R, P>& d)
{
value_type r = d.scale();
r = d.shape();
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::inverse_chi_squared_distribution<R, P>& d)
{
value_type r = d.scale();
r = d.degrees_of_freedom();
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::inverse_gamma_distribution<R, P>& d)
{
value_type r = d.scale();
r = d.shape();
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::hypergeometric_distribution<R, P>& d)
{
unsigned u = d.defective();
u = d.sample_count();
u = d.total();
suppress_unused_variable_warning(u);
}
template <class R, class P>
static void test_extra_members(const boost::math::laplace_distribution<R, P>& d)
{
value_type r = d.scale();
r = d.location();
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::logistic_distribution<R, P>& d)
{
value_type r = d.scale();
r = d.location();
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::lognormal_distribution<R, P>& d)
{
value_type r = d.scale();
r = d.location();
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::negative_binomial_distribution<R, P>& d)
{
value_type r = d.success_fraction();
r = d.successes();
r = Distribution::find_lower_bound_on_p(r, r, r);
r = Distribution::find_upper_bound_on_p(r, r, r);
r = Distribution::find_minimum_number_of_trials(r, r, r);
r = Distribution::find_maximum_number_of_trials(r, r, r);
suppress_unused_variable_warning(r);
}
template <class R, class P>
static void test_extra_members(const boost::math::non_central_beta_distribution<R, P>& d)
{
value_type r1 = d.alpha();
value_type r2 = d.beta();
r1 = d.non_centrality();
(void)r1; // warning suppression
(void)r2; // warning suppression
}
template <class R, class P>
static void test_extra_members(const boost::math::non_central_chi_squared_distribution<R, P>& d)
{
value_type r = d.degrees_of_freedom();
r = d.non_centrality();
r = Distribution::find_degrees_of_freedom(r, r, r);
r = Distribution::find_degrees_of_freedom(boost::math::complement(r, r, r));
r = Distribution::find_non_centrality(r, r, r);
r = Distribution::find_non_centrality(boost::math::complement(r, r, r));
(void)r; // warning suppression
}
template <class R, class P>
static void test_extra_members(const boost::math::non_central_f_distribution<R, P>& d)
{
value_type r = d.degrees_of_freedom1();
r = d.degrees_of_freedom2();
r = d.non_centrality();
(void)r; // warning suppression
}
template <class R, class P>
static void test_extra_members(const boost::math::non_central_t_distribution<R, P>& d)
{
value_type r = d.degrees_of_freedom();
r = d.non_centrality();
(void)r; // warning suppression
}
template <class R, class P>
static void test_extra_members(const boost::math::normal_distribution<R, P>& d)
{
value_type r = d.scale();
r = d.location();
r = d.mean();
r = d.standard_deviation();
(void)r; // warning suppression
}
template <class R, class P>
static void test_extra_members(const boost::math::pareto_distribution<R, P>& d)
{
value_type r = d.scale();
r = d.shape();
(void)r; // warning suppression
}
template <class R, class P>
static void test_extra_members(const boost::math::poisson_distribution<R, P>& d)
{
value_type r = d.mean();
(void)r; // warning suppression
}
template <class R, class P>
static void test_extra_members(const boost::math::rayleigh_distribution<R, P>& d)
{
value_type r = d.sigma();
(void)r; // warning suppression
}
template <class R, class P>
static void test_extra_members(const boost::math::students_t_distribution<R, P>& d)
{
value_type r = d.degrees_of_freedom();
r = d.find_degrees_of_freedom(r, r, r, r);
r = d.find_degrees_of_freedom(r, r, r, r, r);
(void)r; // warning suppression
}
template <class R, class P>
static void test_extra_members(const boost::math::triangular_distribution<R, P>& d)
{
value_type r = d.lower();
r = d.mode();
r = d.upper();
(void)r; // warning suppression
}
template <class R, class P>
static void test_extra_members(const boost::math::weibull_distribution<R, P>& d)
{
value_type r = d.scale();
r = d.shape();
(void)r; // warning suppression
}
template <class R, class P>
static void test_extra_members(const boost::math::uniform_distribution<R, P>& d)
{
value_type r = d.lower();
r = d.upper();
(void)r; // warning suppression
}
private:
static Distribution* pd;
static Distribution& get_object()
{
// In reality this will never get called:
return *pd;
}
}; // struct DistributionConcept
template <class Distribution>
Distribution* DistributionConcept<Distribution>::pd = 0;
} // namespace concepts
} // namespace math
} // namespace boost
#endif // BOOST_MATH_DISTRIBUTION_CONCEPT_HPP

View File

@@ -0,0 +1,478 @@
// 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".
#ifndef BOOST_MATH_REAL_CONCEPT_HPP
#define BOOST_MATH_REAL_CONCEPT_HPP
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/math/special_functions/round.hpp>
#include <boost/math/special_functions/trunc.hpp>
#include <boost/math/special_functions/modf.hpp>
#include <boost/math/tools/big_constant.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/math/policies/policy.hpp>
#if defined(__SGI_STL_PORT)
# include <boost/math/tools/real_cast.hpp>
#endif
#include <ostream>
#include <istream>
#include <boost/config/no_tr1/cmath.hpp>
#include <math.h> // fmodl
#if defined(__SGI_STL_PORT) || defined(_RWSTD_VER) || defined(__LIBCOMO__)
# include <cstdio>
#endif
namespace boost{ namespace math{
namespace concepts
{
#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
typedef double real_concept_base_type;
#else
typedef long double real_concept_base_type;
#endif
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){}
#if defined(__DECCXX) || defined(__SUNPRO_CC)
real_concept(unsigned long long c) : m_value(static_cast<real_concept_base_type>(c)){}
real_concept(long long c) : m_value(static_cast<real_concept_base_type>(c)){}
#elif defined(BOOST_HAS_LONG_LONG)
real_concept(boost::ulong_long_type c) : m_value(static_cast<real_concept_base_type>(c)){}
real_concept(boost::long_long_type c) : m_value(static_cast<real_concept_base_type>(c)){}
#elif defined(BOOST_HAS_MS_INT64)
real_concept(unsigned __int64 c) : m_value(static_cast<real_concept_base_type>(c)){}
real_concept(__int64 c) : m_value(static_cast<real_concept_base_type>(c)){}
#endif
real_concept(float c) : m_value(c){}
real_concept(double c) : m_value(c){}
real_concept(long double c) : m_value(c){}
#ifdef BOOST_MATH_USE_FLOAT128
real_concept(BOOST_MATH_FLOAT128_TYPE c) : m_value(c){}
#endif
// 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=(boost::long_long_type c) { m_value = static_cast<real_concept_base_type>(c); return *this; }
real_concept& operator=(boost::ulong_long_type c) { m_value = static_cast<real_concept_base_type>(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:
real_concept_base_type 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; }
real_concept& operator++()
{ ++m_value; return *this; }
real_concept& operator--()
{ --m_value; return *this; }
private:
real_concept_base_type 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(); }
// 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()); }
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
// I've seen std::fmod(long double) crash on some platforms
// so use fmodl instead:
#ifdef _WIN32_WCE
//
// Ugly workaround for macro fmodl:
//
inline long double call_fmodl(long double a, long double b)
{ return fmodl(a, b); }
inline real_concept fmod(real_concept a, real_concept b)
{ return call_fmodl(a.value(), b.value()); }
#else
inline real_concept fmod(real_concept a, real_concept b)
{ return fmodl(a.value(), b.value()); }
#endif
#endif
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)
{
#ifdef __MINGW32__
real_concept_base_type ip;
real_concept_base_type result = boost::math::modf(a.value(), &ip);
*ipart = ip;
return result;
#else
real_concept_base_type ip;
real_concept_base_type result = std::modf(a.value(), &ip);
*ipart = ip;
return result;
#endif
}
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()); }
#if !defined(__SUNPRO_CC)
inline real_concept pow(real_concept a, int b)
{ return std::pow(a.value(), b); }
#else
inline real_concept pow(real_concept a, int b)
{ return std::pow(a.value(), static_cast<real_concept_base_type>(b)); }
#endif
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()); }
//
// Conversion and truncation routines:
//
template <class Policy>
inline int iround(const concepts::real_concept& v, const Policy& pol)
{ return boost::math::iround(v.value(), pol); }
inline int iround(const concepts::real_concept& v)
{ return boost::math::iround(v.value(), policies::policy<>()); }
template <class Policy>
inline long lround(const concepts::real_concept& v, const Policy& pol)
{ return boost::math::lround(v.value(), pol); }
inline long lround(const concepts::real_concept& v)
{ return boost::math::lround(v.value(), policies::policy<>()); }
#ifdef BOOST_HAS_LONG_LONG
template <class Policy>
inline boost::long_long_type llround(const concepts::real_concept& v, const Policy& pol)
{ return boost::math::llround(v.value(), pol); }
inline boost::long_long_type llround(const concepts::real_concept& v)
{ return boost::math::llround(v.value(), policies::policy<>()); }
#endif
template <class Policy>
inline int itrunc(const concepts::real_concept& v, const Policy& pol)
{ return boost::math::itrunc(v.value(), pol); }
inline int itrunc(const concepts::real_concept& v)
{ return boost::math::itrunc(v.value(), policies::policy<>()); }
template <class Policy>
inline long ltrunc(const concepts::real_concept& v, const Policy& pol)
{ return boost::math::ltrunc(v.value(), pol); }
inline long ltrunc(const concepts::real_concept& v)
{ return boost::math::ltrunc(v.value(), policies::policy<>()); }
#ifdef BOOST_HAS_LONG_LONG
template <class Policy>
inline boost::long_long_type lltrunc(const concepts::real_concept& v, const Policy& pol)
{ return boost::math::lltrunc(v.value(), pol); }
inline boost::long_long_type lltrunc(const concepts::real_concept& v)
{ return boost::math::lltrunc(v.value(), policies::policy<>()); }
#endif
// 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)
{
#if defined(BOOST_MSVC) && defined(__SGI_STL_PORT)
//
// STLPort 5.1.4 has a problem reading long doubles from strings,
// see http://sourceforge.net/tracker/index.php?func=detail&aid=1811043&group_id=146814&atid=766244
//
double v;
is >> v;
a = v;
return is;
#elif defined(__SGI_STL_PORT) || defined(_RWSTD_VER) || defined(__LIBCOMO__) || defined(_LIBCPP_VERSION)
std::string s;
real_concept_base_type d;
is >> s;
std::sscanf(s.c_str(), "%Lf", &d);
a = d;
return is;
#else
real_concept_base_type v;
is >> v;
a = v;
return is;
#endif
}
} // namespace concepts
namespace tools
{
template <>
inline concepts::real_concept make_big_value<concepts::real_concept>(boost::math::tools::largest_float val, const char* , mpl::false_ const&, mpl::false_ const&)
{
return val; // Can't use lexical_cast here, sometimes it fails....
}
template <>
inline concepts::real_concept max_value<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
{
return max_value<concepts::real_concept_base_type>();
}
template <>
inline concepts::real_concept min_value<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
{
return min_value<concepts::real_concept_base_type>();
}
template <>
inline concepts::real_concept log_max_value<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
{
return log_max_value<concepts::real_concept_base_type>();
}
template <>
inline concepts::real_concept log_min_value<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
{
return log_min_value<concepts::real_concept_base_type>();
}
template <>
inline concepts::real_concept epsilon<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
{
#ifdef __SUNPRO_CC
return std::numeric_limits<concepts::real_concept_base_type>::epsilon();
#else
return tools::epsilon<concepts::real_concept_base_type>();
#endif
}
template <>
inline BOOST_MATH_CONSTEXPR int digits<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept)) BOOST_NOEXCEPT
{
// Assume number of significand bits is same as real_concept_base_type,
// unless std::numeric_limits<T>::is_specialized to provide digits.
return tools::digits<concepts::real_concept_base_type>();
// 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 policies {
namespace detail {
template <class T>
inline concepts::real_concept raise_rounding_error(
const char*,
const char*,
const T& val,
const concepts::real_concept&,
const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
{
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 > 0 ? boost::math::tools::max_value<concepts::real_concept>() : -boost::math::tools::max_value<concepts::real_concept>();
}
}
}*/
#if defined(__SGI_STL_PORT) || defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS)
//
// We shouldn't really need these type casts any more, but there are some
// STLport iostream bugs we work around by using them....
//
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();
}
} // STLPort
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
//
// For some strange reason ADL sometimes fails to find the
// correct overloads, unless we bring these declarations into scope:
//
using concepts::itrunc;
using concepts::iround;
#endif
} // namespace math
} // namespace boost
#endif // BOOST_MATH_REAL_CONCEPT_HPP

View File

@@ -0,0 +1,122 @@
// Copyright John Maddock 2007-8.
// 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_REAL_TYPE_CONCEPT_HPP
#define BOOST_MATH_REAL_TYPE_CONCEPT_HPP
#include <boost/config.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 <boost/math/tools/config.hpp>
#include <boost/math/tools/precision.hpp>
namespace boost{ namespace math{ namespace concepts{
template <class RealType>
struct RealTypeConcept
{
template <class Other>
void check_binary_ops(Other o)
{
RealType r(o);
r = o;
r -= o;
r += o;
r *= o;
r /= o;
r = r - o;
r = o - r;
r = r + o;
r = o + r;
r = o * r;
r = r * o;
r = r / o;
r = o / r;
bool b;
b = r == o;
suppress_unused_variable_warning(b);
b = o == r;
suppress_unused_variable_warning(b);
b = r != o;
suppress_unused_variable_warning(b);
b = o != r;
suppress_unused_variable_warning(b);
b = r <= o;
suppress_unused_variable_warning(b);
b = o <= r;
suppress_unused_variable_warning(b);
b = r >= o;
suppress_unused_variable_warning(b);
b = o >= r;
suppress_unused_variable_warning(b);
b = r < o;
suppress_unused_variable_warning(b);
b = o < r;
suppress_unused_variable_warning(b);
b = r > o;
suppress_unused_variable_warning(b);
b = o > r;
suppress_unused_variable_warning(b);
}
void constraints()
{
BOOST_MATH_STD_USING
RealType r;
check_binary_ops(r);
check_binary_ops(0.5f);
check_binary_ops(0.5);
//check_binary_ops(0.5L);
check_binary_ops(1);
//check_binary_ops(1u);
check_binary_ops(1L);
//check_binary_ops(1uL);
#ifndef BOOST_HAS_LONG_LONG
check_binary_ops(1LL);
#endif
RealType r2 = +r;
r2 = -r;
r2 = fabs(r);
r2 = abs(r);
r2 = ceil(r);
r2 = floor(r);
r2 = exp(r);
r2 = pow(r, r2);
r2 = sqrt(r);
r2 = log(r);
r2 = cos(r);
r2 = sin(r);
r2 = tan(r);
r2 = asin(r);
r2 = acos(r);
r2 = atan(r);
int i;
r2 = ldexp(r, i);
r2 = frexp(r, &i);
i = boost::math::tools::digits<RealType>();
r2 = boost::math::tools::max_value<RealType>();
r2 = boost::math::tools::min_value<RealType>();
r2 = boost::math::tools::log_max_value<RealType>();
r2 = boost::math::tools::log_min_value<RealType>();
r2 = boost::math::tools::epsilon<RealType>();
}
}; // struct DistributionConcept
}}} // namespaces
#endif

View File

@@ -0,0 +1,405 @@
// 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/policies/policy.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
#include <ostream>
#include <istream>
#include <boost/config/no_tr1/cmath.hpp>
#include <math.h> // fmodl
#ifndef BOOST_MATH_STD_REAL_CONCEPT_HPP
#define BOOST_MATH_STD_REAL_CONCEPT_HPP
namespace boost{ namespace math{
namespace concepts
{
#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
typedef double std_real_concept_base_type;
#else
typedef long double std_real_concept_base_type;
#endif
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){}
#if defined(__DECCXX) || defined(__SUNPRO_CC)
std_real_concept(unsigned long long c) : m_value(static_cast<std_real_concept_base_type>(c)){}
std_real_concept(long long c) : m_value(static_cast<std_real_concept_base_type>(c)){}
#elif defined(BOOST_HAS_LONG_LONG)
std_real_concept(boost::ulong_long_type c) : m_value(static_cast<std_real_concept_base_type>(c)){}
std_real_concept(boost::long_long_type c) : m_value(static_cast<std_real_concept_base_type>(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){}
#ifdef BOOST_MATH_USE_FLOAT128
std_real_concept(BOOST_MATH_FLOAT128_TYPE c) : m_value(c){}
#endif
// 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; }
#if defined(__DECCXX) || defined(__SUNPRO_CC)
std_real_concept& operator=(unsigned long long c) { m_value = static_cast<std_real_concept_base_type>(c); return *this; }
std_real_concept& operator=(long long c) { m_value = static_cast<std_real_concept_base_type>(c); return *this; }
#elif defined(BOOST_HAS_LONG_LONG)
std_real_concept& operator=(boost::long_long_type c) { m_value = static_cast<std_real_concept_base_type>(c); return *this; }
std_real_concept& operator=(boost::ulong_long_type c) { m_value = static_cast<std_real_concept_base_type>(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:
std_real_concept_base_type 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:
std_real_concept_base_type 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(); }
} // 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()); }
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
inline boost::math::concepts::std_real_concept fmod(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b)
{ return fmodl(a.value(), b.value()); }
#else
inline boost::math::concepts::std_real_concept fmod(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b)
{ return std::fmod(a.value(), b.value()); }
#endif
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)
{
boost::math::concepts::std_real_concept_base_type ip;
boost::math::concepts::std_real_concept_base_type 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()); }
#if !defined(__SUNPRO_CC)
inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, int b)
{ return std::pow(a.value(), b); }
#else
inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, int b)
{ return std::pow(a.value(), static_cast<long double>(b)); }
#endif
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
#include <boost/math/special_functions/round.hpp>
#include <boost/math/special_functions/trunc.hpp>
#include <boost/math/special_functions/modf.hpp>
#include <boost/math/tools/precision.hpp>
namespace boost{ namespace math{ namespace concepts{
//
// Conversion and truncation routines:
//
template <class Policy>
inline int iround(const concepts::std_real_concept& v, const Policy& pol)
{
return boost::math::iround(v.value(), pol);
}
inline int iround(const concepts::std_real_concept& v)
{
return boost::math::iround(v.value(), policies::policy<>());
}
template <class Policy>
inline long lround(const concepts::std_real_concept& v, const Policy& pol)
{
return boost::math::lround(v.value(), pol);
}
inline long lround(const concepts::std_real_concept& v)
{
return boost::math::lround(v.value(), policies::policy<>());
}
#ifdef BOOST_HAS_LONG_LONG
template <class Policy>
inline boost::long_long_type llround(const concepts::std_real_concept& v, const Policy& pol)
{
return boost::math::llround(v.value(), pol);
}
inline boost::long_long_type llround(const concepts::std_real_concept& v)
{
return boost::math::llround(v.value(), policies::policy<>());
}
#endif
template <class Policy>
inline int itrunc(const concepts::std_real_concept& v, const Policy& pol)
{
return boost::math::itrunc(v.value(), pol);
}
inline int itrunc(const concepts::std_real_concept& v)
{
return boost::math::itrunc(v.value(), policies::policy<>());
}
template <class Policy>
inline long ltrunc(const concepts::std_real_concept& v, const Policy& pol)
{
return boost::math::ltrunc(v.value(), pol);
}
inline long ltrunc(const concepts::std_real_concept& v)
{
return boost::math::ltrunc(v.value(), policies::policy<>());
}
#ifdef BOOST_HAS_LONG_LONG
template <class Policy>
inline boost::long_long_type lltrunc(const concepts::std_real_concept& v, const Policy& pol)
{
return boost::math::lltrunc(v.value(), pol);
}
inline boost::long_long_type lltrunc(const concepts::std_real_concept& v)
{
return boost::math::lltrunc(v.value(), policies::policy<>());
}
#endif
// 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)
{
#if defined(__SGI_STL_PORT) || defined(_RWSTD_VER) || defined(__LIBCOMO__) || defined(_LIBCPP_VERSION)
std::string s;
std_real_concept_base_type d;
is >> s;
std::sscanf(s.c_str(), "%Lf", &d);
a = d;
return is;
#else
std_real_concept_base_type v;
is >> v;
a = v;
return is;
#endif
}
} // namespace concepts
}}
#include <boost/math/tools/precision.hpp>
#include <boost/math/tools/big_constant.hpp>
namespace boost{ namespace math{
namespace tools
{
template <>
inline concepts::std_real_concept make_big_value<concepts::std_real_concept>(boost::math::tools::largest_float val, const char*, mpl::false_ const&, mpl::false_ const&)
{
return val; // Can't use lexical_cast here, sometimes it fails....
}
template <>
inline concepts::std_real_concept max_value<concepts::std_real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
{
return max_value<concepts::std_real_concept_base_type>();
}
template <>
inline concepts::std_real_concept min_value<concepts::std_real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
{
return min_value<concepts::std_real_concept_base_type>();
}
template <>
inline concepts::std_real_concept log_max_value<concepts::std_real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
{
return log_max_value<concepts::std_real_concept_base_type>();
}
template <>
inline concepts::std_real_concept log_min_value<concepts::std_real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
{
return log_min_value<concepts::std_real_concept_base_type>();
}
template <>
inline concepts::std_real_concept epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
{
return tools::epsilon<concepts::std_real_concept_base_type>();
}
template <>
inline BOOST_MATH_CONSTEXPR int digits<concepts::std_real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept)) BOOST_NOEXCEPT
{ // Assume number of significand bits is same as std_real_concept_base_type,
// unless std::numeric_limits<T>::is_specialized to provide digits.
return digits<concepts::std_real_concept_base_type>();
}
} // namespace tools
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
using concepts::itrunc;
using concepts::ltrunc;
using concepts::lltrunc;
using concepts::iround;
using concepts::lround;
using concepts::llround;
#endif
} // namespace math
} // namespace boost
#endif // BOOST_MATH_STD_REAL_CONCEPT_HPP

View File

@@ -0,0 +1,968 @@
// Copyright John Maddock 2010, 2012.
// Copyright Paul A. Bristow 2011, 2012.
// 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_CALCULATE_CONSTANTS_CONSTANTS_INCLUDED
#define BOOST_MATH_CALCULATE_CONSTANTS_CONSTANTS_INCLUDED
#include <boost/math/special_functions/trunc.hpp>
namespace boost{ namespace math{ namespace constants{ namespace detail{
template <class T>
template<int N>
inline T constant_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return ldexp(acos(T(0)), 1);
/*
// Although this code works well, it's usually more accurate to just call acos
// and access the number types own representation of PI which is usually calculated
// at slightly higher precision...
T result;
T a = 1;
T b;
T A(a);
T B = 0.5f;
T D = 0.25f;
T lim;
lim = boost::math::tools::epsilon<T>();
unsigned k = 1;
do
{
result = A + B;
result = ldexp(result, -2);
b = sqrt(B);
a += b;
a = ldexp(a, -1);
A = a * a;
B = A - result;
B = ldexp(B, 1);
result = A - B;
bool neg = boost::math::sign(result) < 0;
if(neg)
result = -result;
if(result <= lim)
break;
if(neg)
result = -result;
result = ldexp(result, k - 1);
D -= result;
++k;
lim = ldexp(lim, 1);
}
while(true);
result = B / D;
return result;
*/
}
template <class T>
template<int N>
inline T constant_two_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
return 2 * pi<T, policies::policy<policies::digits2<N> > >();
}
template <class T> // 2 / pi
template<int N>
inline T constant_two_div_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
return 2 / pi<T, policies::policy<policies::digits2<N> > >();
}
template <class T> // sqrt(2/pi)
template <int N>
inline T constant_root_two_div_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return sqrt((2 / pi<T, policies::policy<policies::digits2<N> > >()));
}
template <class T>
template<int N>
inline T constant_one_div_two_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
return 1 / two_pi<T, policies::policy<policies::digits2<N> > >();
}
template <class T>
template<int N>
inline T constant_root_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return sqrt(pi<T, policies::policy<policies::digits2<N> > >());
}
template <class T>
template<int N>
inline T constant_root_half_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return sqrt(pi<T, policies::policy<policies::digits2<N> > >() / 2);
}
template <class T>
template<int N>
inline T constant_root_two_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return sqrt(two_pi<T, policies::policy<policies::digits2<N> > >());
}
template <class T>
template<int N>
inline T constant_log_root_two_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return log(root_two_pi<T, policies::policy<policies::digits2<N> > >());
}
template <class T>
template<int N>
inline T constant_root_ln_four<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return sqrt(log(static_cast<T>(4)));
}
template <class T>
template<int N>
inline T constant_e<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
//
// Although we can clearly calculate this from first principles, this hooks into
// T's own notion of e, which hopefully will more accurate than one calculated to
// a few epsilon:
//
BOOST_MATH_STD_USING
return exp(static_cast<T>(1));
}
template <class T>
template<int N>
inline T constant_half<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
return static_cast<T>(1) / static_cast<T>(2);
}
template <class T>
template<int M>
inline T constant_euler<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<M>))
{
BOOST_MATH_STD_USING
//
// This is the method described in:
// "Some New Algorithms for High-Precision Computation of Euler's Constant"
// Richard P Brent and Edwin M McMillan.
// Mathematics of Computation, Volume 34, Number 149, Jan 1980, pages 305-312.
// See equation 17 with p = 2.
//
T n = 3 + (M ? (std::min)(M, tools::digits<T>()) : tools::digits<T>()) / 4;
T lim = M ? ldexp(T(1), 1 - (std::min)(M, tools::digits<T>())) : tools::epsilon<T>();
T lnn = log(n);
T term = 1;
T N = -lnn;
T D = 1;
T Hk = 0;
T one = 1;
for(unsigned k = 1;; ++k)
{
term *= n * n;
term /= k * k;
Hk += one / k;
N += term * (Hk - lnn);
D += term;
if(term < D * lim)
break;
}
return N / D;
}
template <class T>
template<int N>
inline T constant_euler_sqr<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return euler<T, policies::policy<policies::digits2<N> > >()
* euler<T, policies::policy<policies::digits2<N> > >();
}
template <class T>
template<int N>
inline T constant_one_div_euler<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return static_cast<T>(1)
/ euler<T, policies::policy<policies::digits2<N> > >();
}
template <class T>
template<int N>
inline T constant_root_two<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return sqrt(static_cast<T>(2));
}
template <class T>
template<int N>
inline T constant_root_three<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return sqrt(static_cast<T>(3));
}
template <class T>
template<int N>
inline T constant_half_root_two<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return sqrt(static_cast<T>(2)) / 2;
}
template <class T>
template<int N>
inline T constant_ln_two<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
//
// Although there are good ways to calculate this from scratch, this hooks into
// T's own notion of log(2) which will hopefully be accurate to the full precision
// of T:
//
BOOST_MATH_STD_USING
return log(static_cast<T>(2));
}
template <class T>
template<int N>
inline T constant_ln_ten<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return log(static_cast<T>(10));
}
template <class T>
template<int N>
inline T constant_ln_ln_two<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return log(log(static_cast<T>(2)));
}
template <class T>
template<int N>
inline T constant_third<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return static_cast<T>(1) / static_cast<T>(3);
}
template <class T>
template<int N>
inline T constant_twothirds<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return static_cast<T>(2) / static_cast<T>(3);
}
template <class T>
template<int N>
inline T constant_two_thirds<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return static_cast<T>(2) / static_cast<T>(3);
}
template <class T>
template<int N>
inline T constant_three_quarters<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return static_cast<T>(3) / static_cast<T>(4);
}
template <class T>
template<int N>
inline T constant_pi_minus_three<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
return pi<T, policies::policy<policies::digits2<N> > >() - static_cast<T>(3);
}
template <class T>
template<int N>
inline T constant_four_minus_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
return static_cast<T>(4) - pi<T, policies::policy<policies::digits2<N> > >();
}
//template <class T>
//template<int N>
//inline T constant_pow23_four_minus_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
//{
// BOOST_MATH_STD_USING
// return pow(four_minus_pi<T, policies::policy<policies::digits2<N> > >(), static_cast<T>(1.5));
//}
template <class T>
template<int N>
inline T constant_exp_minus_half<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return exp(static_cast<T>(-0.5));
}
// Pi
template <class T>
template<int N>
inline T constant_one_div_root_two<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
return static_cast<T>(1) / root_two<T, policies::policy<policies::digits2<N> > >();
}
template <class T>
template<int N>
inline T constant_one_div_root_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
return static_cast<T>(1) / root_pi<T, policies::policy<policies::digits2<N> > >();
}
template <class T>
template<int N>
inline T constant_one_div_root_two_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
return static_cast<T>(1) / root_two_pi<T, policies::policy<policies::digits2<N> > >();
}
template <class T>
template<int N>
inline T constant_root_one_div_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return sqrt(static_cast<T>(1) / pi<T, policies::policy<policies::digits2<N> > >());
}
template <class T>
template<int N>
inline T constant_four_thirds_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pi<T, policies::policy<policies::digits2<N> > >() * static_cast<T>(4) / static_cast<T>(3);
}
template <class T>
template<int N>
inline T constant_half_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pi<T, policies::policy<policies::digits2<N> > >() / static_cast<T>(2);
}
template <class T>
template<int N>
inline T constant_third_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pi<T, policies::policy<policies::digits2<N> > >() / static_cast<T>(3);
}
template <class T>
template<int N>
inline T constant_sixth_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pi<T, policies::policy<policies::digits2<N> > >() / static_cast<T>(6);
}
template <class T>
template<int N>
inline T constant_two_thirds_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pi<T, policies::policy<policies::digits2<N> > >() * static_cast<T>(2) / static_cast<T>(3);
}
template <class T>
template<int N>
inline T constant_three_quarters_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pi<T, policies::policy<policies::digits2<N> > >() * static_cast<T>(3) / static_cast<T>(4);
}
template <class T>
template<int N>
inline T constant_pi_pow_e<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pow(pi<T, policies::policy<policies::digits2<N> > >(), e<T, policies::policy<policies::digits2<N> > >()); //
}
template <class T>
template<int N>
inline T constant_pi_sqr<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pi<T, policies::policy<policies::digits2<N> > >()
* pi<T, policies::policy<policies::digits2<N> > >() ; //
}
template <class T>
template<int N>
inline T constant_pi_sqr_div_six<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pi<T, policies::policy<policies::digits2<N> > >()
* pi<T, policies::policy<policies::digits2<N> > >()
/ static_cast<T>(6); //
}
template <class T>
template<int N>
inline T constant_pi_cubed<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pi<T, policies::policy<policies::digits2<N> > >()
* pi<T, policies::policy<policies::digits2<N> > >()
* pi<T, policies::policy<policies::digits2<N> > >()
; //
}
template <class T>
template<int N>
inline T constant_cbrt_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pow(pi<T, policies::policy<policies::digits2<N> > >(), static_cast<T>(1)/ static_cast<T>(3));
}
template <class T>
template<int N>
inline T constant_one_div_cbrt_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return static_cast<T>(1)
/ pow(pi<T, policies::policy<policies::digits2<N> > >(), static_cast<T>(1)/ static_cast<T>(3));
}
// Euler's e
template <class T>
template<int N>
inline T constant_e_pow_pi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pow(e<T, policies::policy<policies::digits2<N> > >(), pi<T, policies::policy<policies::digits2<N> > >()); //
}
template <class T>
template<int N>
inline T constant_root_e<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return sqrt(e<T, policies::policy<policies::digits2<N> > >());
}
template <class T>
template<int N>
inline T constant_log10_e<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return log10(e<T, policies::policy<policies::digits2<N> > >());
}
template <class T>
template<int N>
inline T constant_one_div_log10_e<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return static_cast<T>(1) /
log10(e<T, policies::policy<policies::digits2<N> > >());
}
// Trigonometric
template <class T>
template<int N>
inline T constant_degree<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pi<T, policies::policy<policies::digits2<N> > >()
/ static_cast<T>(180)
; //
}
template <class T>
template<int N>
inline T constant_radian<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return static_cast<T>(180)
/ pi<T, policies::policy<policies::digits2<N> > >()
; //
}
template <class T>
template<int N>
inline T constant_sin_one<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return sin(static_cast<T>(1)) ; //
}
template <class T>
template<int N>
inline T constant_cos_one<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return cos(static_cast<T>(1)) ; //
}
template <class T>
template<int N>
inline T constant_sinh_one<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return sinh(static_cast<T>(1)) ; //
}
template <class T>
template<int N>
inline T constant_cosh_one<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return cosh(static_cast<T>(1)) ; //
}
template <class T>
template<int N>
inline T constant_phi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return (static_cast<T>(1) + sqrt(static_cast<T>(5)) )/static_cast<T>(2) ; //
}
template <class T>
template<int N>
inline T constant_ln_phi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
//return log(phi<T, policies::policy<policies::digits2<N> > >()); // ???
return log((static_cast<T>(1) + sqrt(static_cast<T>(5)) )/static_cast<T>(2) );
}
template <class T>
template<int N>
inline T constant_one_div_ln_phi<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return static_cast<T>(1) /
log((static_cast<T>(1) + sqrt(static_cast<T>(5)) )/static_cast<T>(2) );
}
// Zeta
template <class T>
template<int N>
inline T constant_zeta_two<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
return pi<T, policies::policy<policies::digits2<N> > >()
* pi<T, policies::policy<policies::digits2<N> > >()
/static_cast<T>(6);
}
template <class T>
template<int N>
inline T constant_zeta_three<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
// http://mathworld.wolfram.com/AperysConstant.html
// http://en.wikipedia.org/wiki/Mathematical_constant
// http://oeis.org/A002117/constant
//T zeta3("1.20205690315959428539973816151144999076"
// "4986292340498881792271555341838205786313"
// "09018645587360933525814619915");
//"1.202056903159594285399738161511449990, 76498629234049888179227155534183820578631309018645587360933525814619915" A002117
// 1.202056903159594285399738161511449990, 76498629234049888179227155534183820578631309018645587360933525814619915780, +00);
//"1.2020569031595942 double
// http://www.spaennare.se/SSPROG/ssnum.pdf // section 11, Algorithm for Apery's constant zeta(3).
// Programs to Calculate some Mathematical Constants to Large Precision, Document Version 1.50
// by Stefan Spannare September 19, 2007
// zeta(3) = 1/64 * sum
BOOST_MATH_STD_USING
T n_fact=static_cast<T>(1); // build n! for n = 0.
T sum = static_cast<double>(77); // Start with n = 0 case.
// for n = 0, (77/1) /64 = 1.203125
//double lim = std::numeric_limits<double>::epsilon();
T lim = N ? ldexp(T(1), 1 - (std::min)(N, tools::digits<T>())) : tools::epsilon<T>();
for(unsigned int n = 1; n < 40; ++n)
{ // three to five decimal digits per term, so 40 should be plenty for 100 decimal digits.
//cout << "n = " << n << endl;
n_fact *= n; // n!
T n_fact_p10 = n_fact * n_fact * n_fact * n_fact * n_fact * n_fact * n_fact * n_fact * n_fact * n_fact; // (n!)^10
T num = ((205 * n * n) + (250 * n) + 77) * n_fact_p10; // 205n^2 + 250n + 77
// int nn = (2 * n + 1);
// T d = factorial(nn); // inline factorial.
T d = 1;
for(unsigned int i = 1; i <= (n+n + 1); ++i) // (2n + 1)
{
d *= i;
}
T den = d * d * d * d * d; // [(2n+1)!]^5
//cout << "den = " << den << endl;
T term = num/den;
if (n % 2 != 0)
{ //term *= -1;
sum -= term;
}
else
{
sum += term;
}
//cout << "term = " << term << endl;
//cout << "sum/64 = " << sum/64 << endl;
if(abs(term) < lim)
{
break;
}
}
return sum / 64;
}
template <class T>
template<int N>
inline T constant_catalan<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{ // http://oeis.org/A006752/constant
//T c("0.915965594177219015054603514932384110774"
//"149374281672134266498119621763019776254769479356512926115106248574");
// 9.159655941772190150546035149323841107, 74149374281672134266498119621763019776254769479356512926115106248574422619, -01);
// This is equation (entry) 31 from
// http://www-2.cs.cmu.edu/~adamchik/articles/catalan/catalan.htm
// See also http://www.mpfr.org/algorithms.pdf
BOOST_MATH_STD_USING
T k_fact = 1;
T tk_fact = 1;
T sum = 1;
T term;
T lim = N ? ldexp(T(1), 1 - (std::min)(N, tools::digits<T>())) : tools::epsilon<T>();
for(unsigned k = 1;; ++k)
{
k_fact *= k;
tk_fact *= (2 * k) * (2 * k - 1);
term = k_fact * k_fact / (tk_fact * (2 * k + 1) * (2 * k + 1));
sum += term;
if(term < lim)
{
break;
}
}
return boost::math::constants::pi<T, boost::math::policies::policy<> >()
* log(2 + boost::math::constants::root_three<T, boost::math::policies::policy<> >())
/ 8
+ 3 * sum / 8;
}
namespace khinchin_detail{
template <class T>
T zeta_polynomial_series(T s, T sc, int digits)
{
BOOST_MATH_STD_USING
//
// This is algorithm 3 from:
//
// "An Efficient Algorithm for the Riemann Zeta Function", P. Borwein,
// Canadian Mathematical Society, Conference Proceedings, 2000.
// See: http://www.cecm.sfu.ca/personal/pborwein/PAPERS/P155.pdf
//
BOOST_MATH_STD_USING
int n = (digits * 19) / 53;
T sum = 0;
T two_n = ldexp(T(1), n);
int ej_sign = 1;
for(int j = 0; j < n; ++j)
{
sum += ej_sign * -two_n / pow(T(j + 1), s);
ej_sign = -ej_sign;
}
T ej_sum = 1;
T ej_term = 1;
for(int j = n; j <= 2 * n - 1; ++j)
{
sum += ej_sign * (ej_sum - two_n) / pow(T(j + 1), s);
ej_sign = -ej_sign;
ej_term *= 2 * n - j;
ej_term /= j - n + 1;
ej_sum += ej_term;
}
return -sum / (two_n * (1 - pow(T(2), sc)));
}
template <class T>
T khinchin(int digits)
{
BOOST_MATH_STD_USING
T sum = 0;
T term;
T lim = ldexp(T(1), 1-digits);
T factor = 0;
unsigned last_k = 1;
T num = 1;
for(unsigned n = 1;; ++n)
{
for(unsigned k = last_k; k <= 2 * n - 1; ++k)
{
factor += num / k;
num = -num;
}
last_k = 2 * n;
term = (zeta_polynomial_series(T(2 * n), T(1 - T(2 * n)), digits) - 1) * factor / n;
sum += term;
if(term < lim)
break;
}
return exp(sum / boost::math::constants::ln_two<T, boost::math::policies::policy<> >());
}
}
template <class T>
template<int N>
inline T constant_khinchin<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
int n = N ? (std::min)(N, tools::digits<T>()) : tools::digits<T>();
return khinchin_detail::khinchin<T>(n);
}
template <class T>
template<int N>
inline T constant_extreme_value_skewness<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{ // from e_float constants.cpp
// Mathematica: N[12 Sqrt[6] Zeta[3]/Pi^3, 1101]
BOOST_MATH_STD_USING
T ev(12 * sqrt(static_cast<T>(6)) * zeta_three<T, policies::policy<policies::digits2<N> > >()
/ pi_cubed<T, policies::policy<policies::digits2<N> > >() );
//T ev(
//"1.1395470994046486574927930193898461120875997958365518247216557100852480077060706857071875468869385150"
//"1894272048688553376986765366075828644841024041679714157616857834895702411080704529137366329462558680"
//"2015498788776135705587959418756809080074611906006528647805347822929577145038743873949415294942796280"
//"0895597703063466053535550338267721294164578901640163603544404938283861127819804918174973533694090594"
//"3094963822672055237678432023017824416203652657301470473548274848068762500300316769691474974950757965"
//"8640779777748741897542093874605477776538884083378029488863880220988107155275203245233994097178778984"
//"3488995668362387892097897322246698071290011857605809901090220903955815127463328974447572119951192970"
//"3684453635456559086126406960279692862247058250100678008419431185138019869693206366891639436908462809"
//"9756051372711251054914491837034685476095423926553367264355374652153595857163724698198860485357368964"
//"3807049634423621246870868566707915720704996296083373077647528285782964567312903914752617978405994377"
//"9064157147206717895272199736902453130842229559980076472936976287378945035706933650987259357729800315");
return ev;
}
namespace detail{
//
// Calculation of the Glaisher constant depends upon calculating the
// derivative of the zeta function at 2, we can then use the relation:
// zeta'(2) = 1/6 pi^2 [euler + ln(2pi)-12ln(A)]
// To get the constant A.
// See equation 45 at http://mathworld.wolfram.com/RiemannZetaFunction.html.
//
// The derivative of the zeta function is computed by direct differentiation
// of the relation:
// (1-2^(1-s))zeta(s) = SUM(n=0, INF){ (-n)^n / (n+1)^s }
// Which gives us 2 slowly converging but alternating sums to compute,
// for this we use Algorithm 1 from "Convergent Acceleration of Alternating Series",
// Henri Cohen, Fernando Rodriguez Villegas and Don Zagier, Experimental Mathematics 9:1 (1999).
// See http://www.math.utexas.edu/users/villegas/publications/conv-accel.pdf
//
template <class T>
T zeta_series_derivative_2(unsigned digits)
{
// Derivative of the series part, evaluated at 2:
BOOST_MATH_STD_USING
int n = digits * 301 * 13 / 10000;
boost::math::itrunc((std::numeric_limits<T>::digits10 + 1) * 1.3);
T d = pow(3 + sqrt(T(8)), n);
d = (d + 1 / d) / 2;
T b = -1;
T c = -d;
T s = 0;
for(int k = 0; k < n; ++k)
{
T a = -log(T(k+1)) / ((k+1) * (k+1));
c = b - c;
s = s + c * a;
b = (k + n) * (k - n) * b / ((k + T(0.5f)) * (k + 1));
}
return s / d;
}
template <class T>
T zeta_series_2(unsigned digits)
{
// Series part of zeta at 2:
BOOST_MATH_STD_USING
int n = digits * 301 * 13 / 10000;
T d = pow(3 + sqrt(T(8)), n);
d = (d + 1 / d) / 2;
T b = -1;
T c = -d;
T s = 0;
for(int k = 0; k < n; ++k)
{
T a = T(1) / ((k + 1) * (k + 1));
c = b - c;
s = s + c * a;
b = (k + n) * (k - n) * b / ((k + T(0.5f)) * (k + 1));
}
return s / d;
}
template <class T>
inline T zeta_series_lead_2()
{
// lead part at 2:
return 2;
}
template <class T>
inline T zeta_series_derivative_lead_2()
{
// derivative of lead part at 2:
return -2 * boost::math::constants::ln_two<T>();
}
template <class T>
inline T zeta_derivative_2(unsigned n)
{
// zeta derivative at 2:
return zeta_series_derivative_2<T>(n) * zeta_series_lead_2<T>()
+ zeta_series_derivative_lead_2<T>() * zeta_series_2<T>(n);
}
} // namespace detail
template <class T>
template<int N>
inline T constant_glaisher<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{
BOOST_MATH_STD_USING
typedef policies::policy<policies::digits2<N> > forwarding_policy;
int n = N ? (std::min)(N, tools::digits<T>()) : tools::digits<T>();
T v = detail::zeta_derivative_2<T>(n);
v *= 6;
v /= boost::math::constants::pi<T, forwarding_policy>() * boost::math::constants::pi<T, forwarding_policy>();
v -= boost::math::constants::euler<T, forwarding_policy>();
v -= log(2 * boost::math::constants::pi<T, forwarding_policy>());
v /= -12;
return exp(v);
/*
// from http://mpmath.googlecode.com/svn/data/glaisher.txt
// 20,000 digits of the Glaisher-Kinkelin constant A = exp(1/2 - zeta'(-1))
// Computed using A = exp((6 (-zeta'(2))/pi^2 + log 2 pi + gamma)/12)
// with Euler-Maclaurin summation for zeta'(2).
T g(
"1.282427129100622636875342568869791727767688927325001192063740021740406308858826"
"46112973649195820237439420646120399000748933157791362775280404159072573861727522"
"14334327143439787335067915257366856907876561146686449997784962754518174312394652"
"76128213808180219264516851546143919901083573730703504903888123418813674978133050"
"93770833682222494115874837348064399978830070125567001286994157705432053927585405"
"81731588155481762970384743250467775147374600031616023046613296342991558095879293"
"36343887288701988953460725233184702489001091776941712153569193674967261270398013"
"52652668868978218897401729375840750167472114895288815996668743164513890306962645"
"59870469543740253099606800842447417554061490189444139386196089129682173528798629"
"88434220366989900606980888785849587494085307347117090132667567503310523405221054"
"14176776156308191919997185237047761312315374135304725819814797451761027540834943"
"14384965234139453373065832325673954957601692256427736926358821692159870775858274"
"69575162841550648585890834128227556209547002918593263079373376942077522290940187");
return g;
*/
}
template <class T>
template<int N>
inline T constant_rayleigh_skewness<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{ // From e_float
// 1100 digits of the Rayleigh distribution skewness
// Mathematica: N[2 Sqrt[Pi] (Pi - 3)/((4 - Pi)^(3/2)), 1100]
BOOST_MATH_STD_USING
T rs(2 * root_pi<T, policies::policy<policies::digits2<N> > >()
* pi_minus_three<T, policies::policy<policies::digits2<N> > >()
/ pow(four_minus_pi<T, policies::policy<policies::digits2<N> > >(), static_cast<T>(3./2))
);
// 6.31110657818937138191899351544227779844042203134719497658094585692926819617473725459905027032537306794400047264,
//"0.6311106578189371381918993515442277798440422031347194976580945856929268196174737254599050270325373067"
//"9440004726436754739597525250317640394102954301685809920213808351450851396781817932734836994829371322"
//"5797376021347531983451654130317032832308462278373358624120822253764532674177325950686466133508511968"
//"2389168716630349407238090652663422922072397393006683401992961569208109477307776249225072042971818671"
//"4058887072693437217879039875871765635655476241624825389439481561152126886932506682176611183750503553"
//"1218982627032068396407180216351425758181396562859085306247387212297187006230007438534686340210168288"
//"8956816965453815849613622117088096547521391672977226658826566757207615552041767516828171274858145957"
//"6137539156656005855905288420585194082284972984285863898582313048515484073396332610565441264220790791"
//"0194897267890422924599776483890102027823328602965235306539844007677157873140562950510028206251529523"
//"7428049693650605954398446899724157486062545281504433364675815915402937209673727753199567661561209251"
//"4695589950526053470201635372590001578503476490223746511106018091907936826431407434894024396366284848"); ;
return rs;
}
template <class T>
template<int N>
inline T constant_rayleigh_kurtosis_excess<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{ // - (6 Pi^2 - 24 Pi + 16)/((Pi - 4)^2)
// Might provide and calculate this using pi_minus_four.
BOOST_MATH_STD_USING
return - (((static_cast<T>(6) * pi<T, policies::policy<policies::digits2<N> > >()
* pi<T, policies::policy<policies::digits2<N> > >())
- (static_cast<T>(24) * pi<T, policies::policy<policies::digits2<N> > >()) + static_cast<T>(16) )
/
((pi<T, policies::policy<policies::digits2<N> > >() - static_cast<T>(4))
* (pi<T, policies::policy<policies::digits2<N> > >() - static_cast<T>(4)))
);
}
template <class T>
template<int N>
inline T constant_rayleigh_kurtosis<T>::compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))
{ // 3 - (6 Pi^2 - 24 Pi + 16)/((Pi - 4)^2)
// Might provide and calculate this using pi_minus_four.
BOOST_MATH_STD_USING
return static_cast<T>(3) - (((static_cast<T>(6) * pi<T, policies::policy<policies::digits2<N> > >()
* pi<T, policies::policy<policies::digits2<N> > >())
- (static_cast<T>(24) * pi<T, policies::policy<policies::digits2<N> > >()) + static_cast<T>(16) )
/
((pi<T, policies::policy<policies::digits2<N> > >() - static_cast<T>(4))
* (pi<T, policies::policy<policies::digits2<N> > >() - static_cast<T>(4)))
);
}
}}}} // namespaces
#endif // BOOST_MATH_CALCULATE_CONSTANTS_CONSTANTS_INCLUDED

View File

@@ -0,0 +1,347 @@
// Copyright John Maddock 2005-2006, 2011.
// Copyright Paul A. Bristow 2006-2011.
// 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/math/tools/config.hpp>
#include <boost/math/policies/policy.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/math/tools/convert_from_string.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4127 4701)
#endif
#ifndef BOOST_MATH_NO_LEXICAL_CAST
#include <boost/lexical_cast.hpp>
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/int.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/declval.hpp>
namespace boost{ namespace math
{
namespace constants
{
// To permit other calculations at about 100 decimal digits with some UDT,
// 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).
enum construction_method
{
construct_from_float = 1,
construct_from_double = 2,
construct_from_long_double = 3,
construct_from_string = 4,
construct_from_float128 = 5,
// Must be the largest value above:
construct_max = construct_from_float128
};
//
// Traits class determines how to convert from string based on whether T has a constructor
// from const char* or not:
//
template <int N>
struct dummy_size{};
//
// Max number of binary digits in the string representations
// of our constants:
//
BOOST_STATIC_CONSTANT(int, max_string_digits = (101 * 1000L) / 301L);
template <class Real, class Policy>
struct construction_traits
{
private:
typedef typename policies::precision<Real, Policy>::type t1;
typedef typename policies::precision<float, Policy>::type t2;
typedef typename policies::precision<double, Policy>::type t3;
typedef typename policies::precision<long double, Policy>::type t4;
#ifdef BOOST_MATH_USE_FLOAT128
typedef mpl::int_<113> t5;
#endif
public:
typedef typename mpl::if_<
mpl::and_<boost::is_convertible<float, Real>, mpl::bool_< t1::value <= t2::value>, mpl::bool_<0 != t1::value> >,
mpl::int_<construct_from_float>,
typename mpl::if_<
mpl::and_<boost::is_convertible<double, Real>, mpl::bool_< t1::value <= t3::value>, mpl::bool_<0 != t1::value> >,
mpl::int_<construct_from_double>,
typename mpl::if_<
mpl::and_<boost::is_convertible<long double, Real>, mpl::bool_< t1::value <= t4::value>, mpl::bool_<0 != t1::value> >,
mpl::int_<construct_from_long_double>,
#ifdef BOOST_MATH_USE_FLOAT128
typename mpl::if_<
mpl::and_<boost::is_convertible<BOOST_MATH_FLOAT128_TYPE, Real>, mpl::bool_< t1::value <= t5::value>, mpl::bool_<0 != t1::value> >,
mpl::int_<construct_from_float128>,
typename mpl::if_<
mpl::and_<mpl::bool_< t1::value <= max_string_digits>, mpl::bool_<0 != t1::value> >,
mpl::int_<construct_from_string>,
mpl::int_<t1::value>
>::type
>::type
#else
typename mpl::if_<
mpl::and_<mpl::bool_< t1::value <= max_string_digits>, mpl::bool_<0 != t1::value> >,
mpl::int_<construct_from_string>,
mpl::int_<t1::value>
>::type
#endif
>::type
>::type
>::type type;
};
#ifdef BOOST_HAS_THREADS
#define BOOST_MATH_CONSTANT_THREAD_HELPER(name, prefix) \
boost::once_flag f = BOOST_ONCE_INIT;\
boost::call_once(f, &BOOST_JOIN(BOOST_JOIN(string_, get_), name)<T>);
#else
#define BOOST_MATH_CONSTANT_THREAD_HELPER(name, prefix)
#endif
namespace detail{
template <class Real, class Policy = boost::math::policies::policy<> >
struct constant_return
{
typedef typename construction_traits<Real, Policy>::type construct_type;
typedef typename mpl::if_c<
(construct_type::value == construct_from_string) || (construct_type::value > construct_max),
const Real&, Real>::type type;
};
template <class T, const T& (*F)()>
struct constant_initializer
{
static void force_instantiate()
{
init.force_instantiate();
}
private:
struct initializer
{
initializer()
{
F();
}
void force_instantiate()const{}
};
static const initializer init;
};
template <class T, const T& (*F)()>
typename constant_initializer<T, F>::initializer const constant_initializer<T, F>::init;
template <class T, int N, const T& (*F)(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
struct constant_initializer2
{
static void force_instantiate()
{
init.force_instantiate();
}
private:
struct initializer
{
initializer()
{
F();
}
void force_instantiate()const{}
};
static const initializer init;
};
template <class T, int N, const T& (*F)(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))>
typename constant_initializer2<T, N, F>::initializer const constant_initializer2<T, N, F>::init;
}
#ifdef BOOST_MATH_USE_FLOAT128
# define BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x) \
static inline BOOST_CONSTEXPR T get(const mpl::int_<construct_from_float128>&) BOOST_NOEXCEPT\
{ return BOOST_JOIN(x, Q); }
#else
# define BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x)
#endif
#ifdef BOOST_NO_CXX11_THREAD_LOCAL
# define BOOST_MATH_PRECOMPUTE_IF_NOT_LOCAL(constant_, name) constant_initializer<T, & BOOST_JOIN(constant_, name)<T>::get_from_variable_precision>::force_instantiate();
#else
# define BOOST_MATH_PRECOMPUTE_IF_NOT_LOCAL(constant_, name)
#endif
#define BOOST_DEFINE_MATH_CONSTANT(name, x, y)\
namespace detail{\
template <class T> struct BOOST_JOIN(constant_, name){\
private:\
/* The default implementations come next: */ \
static inline const T& get_from_string()\
{\
static const T result(boost::math::tools::convert_from_string<T>(y));\
return result;\
}\
/* This one is for very high precision that is none the less known at compile time: */ \
template <int N> static T compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>));\
template <int N> static inline const T& get_from_compute(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(mpl::int_<N>))\
{\
static const T result = compute<N>();\
return result;\
}\
static inline const T& get_from_variable_precision()\
{\
static BOOST_MATH_THREAD_LOCAL int digits = 0;\
static BOOST_MATH_THREAD_LOCAL T value;\
int current_digits = boost::math::tools::digits<T>();\
if(digits != current_digits)\
{\
value = current_digits > max_string_digits ? compute<0>() : T(boost::math::tools::convert_from_string<T>(y));\
digits = current_digits; \
}\
return value;\
}\
/* public getters come next */\
public:\
static inline const T& get(const mpl::int_<construct_from_string>&)\
{\
constant_initializer<T, & BOOST_JOIN(constant_, name)<T>::get_from_string >::force_instantiate();\
return get_from_string();\
}\
static inline BOOST_CONSTEXPR T get(const mpl::int_<construct_from_float>) BOOST_NOEXCEPT\
{ return BOOST_JOIN(x, F); }\
static inline BOOST_CONSTEXPR T get(const mpl::int_<construct_from_double>&) BOOST_NOEXCEPT\
{ return x; }\
static inline BOOST_CONSTEXPR T get(const mpl::int_<construct_from_long_double>&) BOOST_NOEXCEPT\
{ return BOOST_JOIN(x, L); }\
BOOST_MATH_FLOAT128_CONSTANT_OVERLOAD(x) \
template <int N> static inline const T& get(const mpl::int_<N>&)\
{\
constant_initializer2<T, N, & BOOST_JOIN(constant_, name)<T>::template get_from_compute<N> >::force_instantiate();\
return get_from_compute<N>(); \
}\
/* This one is for true arbitary precision, which may well vary at runtime: */ \
static inline T get(const mpl::int_<0>&)\
{\
BOOST_MATH_PRECOMPUTE_IF_NOT_LOCAL(constant_, name)\
return get_from_variable_precision(); }\
}; /* end of struct */\
} /* namespace detail */ \
\
\
/* The actual forwarding function: */ \
template <class T, class Policy> inline BOOST_CONSTEXPR typename detail::constant_return<T, Policy>::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy)) BOOST_MATH_NOEXCEPT(T)\
{ return detail:: BOOST_JOIN(constant_, name)<T>::get(typename construction_traits<T, Policy>::type()); }\
template <class T> inline BOOST_CONSTEXPR typename detail::constant_return<T>::type name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T)) BOOST_MATH_NOEXCEPT(T)\
{ return name<T, boost::math::policies::policy<> >(); }\
\
\
/* Now the namespace specific versions: */ \
} namespace float_constants{ BOOST_STATIC_CONSTEXPR float name = BOOST_JOIN(x, F); }\
namespace double_constants{ BOOST_STATIC_CONSTEXPR double name = x; } \
namespace long_double_constants{ BOOST_STATIC_CONSTEXPR long double name = BOOST_JOIN(x, L); }\
namespace constants{
BOOST_DEFINE_MATH_CONSTANT(half, 5.000000000000000000000000000000000000e-01, "5.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-01")
BOOST_DEFINE_MATH_CONSTANT(third, 3.333333333333333333333333333333333333e-01, "3.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333e-01")
BOOST_DEFINE_MATH_CONSTANT(twothirds, 6.666666666666666666666666666666666666e-01, "6.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-01")
BOOST_DEFINE_MATH_CONSTANT(two_thirds, 6.666666666666666666666666666666666666e-01, "6.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667e-01")
BOOST_DEFINE_MATH_CONSTANT(three_quarters, 7.500000000000000000000000000000000000e-01, "7.50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-01")
BOOST_DEFINE_MATH_CONSTANT(root_two, 1.414213562373095048801688724209698078e+00, "1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157273501384623e+00")
BOOST_DEFINE_MATH_CONSTANT(root_three, 1.732050807568877293527446341505872366e+00, "1.73205080756887729352744634150587236694280525381038062805580697945193301690880003708114618675724857567562614142e+00")
BOOST_DEFINE_MATH_CONSTANT(half_root_two, 7.071067811865475244008443621048490392e-01, "7.07106781186547524400844362104849039284835937688474036588339868995366239231053519425193767163820786367506923115e-01")
BOOST_DEFINE_MATH_CONSTANT(ln_two, 6.931471805599453094172321214581765680e-01, "6.93147180559945309417232121458176568075500134360255254120680009493393621969694715605863326996418687542001481021e-01")
BOOST_DEFINE_MATH_CONSTANT(ln_ln_two, -3.665129205816643270124391582326694694e-01, "-3.66512920581664327012439158232669469454263447837105263053677713670561615319352738549455822856698908358302523045e-01")
BOOST_DEFINE_MATH_CONSTANT(root_ln_four, 1.177410022515474691011569326459699637e+00, "1.17741002251547469101156932645969963774738568938582053852252575650002658854698492680841813836877081106747157858e+00")
BOOST_DEFINE_MATH_CONSTANT(one_div_root_two, 7.071067811865475244008443621048490392e-01, "7.07106781186547524400844362104849039284835937688474036588339868995366239231053519425193767163820786367506923115e-01")
BOOST_DEFINE_MATH_CONSTANT(pi, 3.141592653589793238462643383279502884e+00, "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651e+00")
BOOST_DEFINE_MATH_CONSTANT(half_pi, 1.570796326794896619231321691639751442e+00, "1.57079632679489661923132169163975144209858469968755291048747229615390820314310449931401741267105853399107404326e+00")
BOOST_DEFINE_MATH_CONSTANT(third_pi, 1.047197551196597746154214461093167628e+00, "1.04719755119659774615421446109316762806572313312503527365831486410260546876206966620934494178070568932738269550e+00")
BOOST_DEFINE_MATH_CONSTANT(sixth_pi, 5.235987755982988730771072305465838140e-01, "5.23598775598298873077107230546583814032861566562517636829157432051302734381034833104672470890352844663691347752e-01")
BOOST_DEFINE_MATH_CONSTANT(two_pi, 6.283185307179586476925286766559005768e+00, "6.28318530717958647692528676655900576839433879875021164194988918461563281257241799725606965068423413596429617303e+00")
BOOST_DEFINE_MATH_CONSTANT(two_thirds_pi, 2.094395102393195492308428922186335256e+00, "2.09439510239319549230842892218633525613144626625007054731662972820521093752413933241868988356141137865476539101e+00")
BOOST_DEFINE_MATH_CONSTANT(three_quarters_pi, 2.356194490192344928846982537459627163e+00, "2.35619449019234492884698253745962716314787704953132936573120844423086230471465674897102611900658780098661106488e+00")
BOOST_DEFINE_MATH_CONSTANT(four_thirds_pi, 4.188790204786390984616857844372670512e+00, "4.18879020478639098461685784437267051226289253250014109463325945641042187504827866483737976712282275730953078202e+00")
BOOST_DEFINE_MATH_CONSTANT(one_div_two_pi, 1.591549430918953357688837633725143620e-01, "1.59154943091895335768883763372514362034459645740456448747667344058896797634226535090113802766253085956072842727e-01")
BOOST_DEFINE_MATH_CONSTANT(one_div_root_two_pi, 3.989422804014326779399460599343818684e-01, "3.98942280401432677939946059934381868475858631164934657665925829670657925899301838501252333907306936430302558863e-01")
BOOST_DEFINE_MATH_CONSTANT(root_pi, 1.772453850905516027298167483341145182e+00, "1.77245385090551602729816748334114518279754945612238712821380778985291128459103218137495065673854466541622682362e+00")
BOOST_DEFINE_MATH_CONSTANT(root_half_pi, 1.253314137315500251207882642405522626e+00, "1.25331413731550025120788264240552262650349337030496915831496178817114682730392098747329791918902863305800498633e+00")
BOOST_DEFINE_MATH_CONSTANT(root_two_pi, 2.506628274631000502415765284811045253e+00, "2.50662827463100050241576528481104525300698674060993831662992357634229365460784197494659583837805726611600997267e+00")
BOOST_DEFINE_MATH_CONSTANT(log_root_two_pi, 9.189385332046727417803297364056176398e-01, "9.18938533204672741780329736405617639861397473637783412817151540482765695927260397694743298635954197622005646625e-01")
BOOST_DEFINE_MATH_CONSTANT(one_div_root_pi, 5.641895835477562869480794515607725858e-01, "5.64189583547756286948079451560772585844050629328998856844085721710642468441493414486743660202107363443028347906e-01")
BOOST_DEFINE_MATH_CONSTANT(root_one_div_pi, 5.641895835477562869480794515607725858e-01, "5.64189583547756286948079451560772585844050629328998856844085721710642468441493414486743660202107363443028347906e-01")
BOOST_DEFINE_MATH_CONSTANT(pi_minus_three, 1.415926535897932384626433832795028841e-01, "1.41592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513e-01")
BOOST_DEFINE_MATH_CONSTANT(four_minus_pi, 8.584073464102067615373566167204971158e-01, "8.58407346410206761537356616720497115802830600624894179025055407692183593713791001371965174657882932017851913487e-01")
//BOOST_DEFINE_MATH_CONSTANT(pow23_four_minus_pi, 7.953167673715975443483953350568065807e-01, "7.95316767371597544348395335056806580727639173327713205445302234388856268267518187590758006888600828436839800178e-01")
BOOST_DEFINE_MATH_CONSTANT(pi_pow_e, 2.245915771836104547342715220454373502e+01, "2.24591577183610454734271522045437350275893151339966922492030025540669260403991179123185197527271430315314500731e+01")
BOOST_DEFINE_MATH_CONSTANT(pi_sqr, 9.869604401089358618834490999876151135e+00, "9.86960440108935861883449099987615113531369940724079062641334937622004482241920524300177340371855223182402591377e+00")
BOOST_DEFINE_MATH_CONSTANT(pi_sqr_div_six, 1.644934066848226436472415166646025189e+00, "1.64493406684822643647241516664602518921894990120679843773555822937000747040320087383362890061975870530400431896e+00")
BOOST_DEFINE_MATH_CONSTANT(pi_cubed, 3.100627668029982017547631506710139520e+01, "3.10062766802998201754763150671013952022252885658851076941445381038063949174657060375667010326028861930301219616e+01")
BOOST_DEFINE_MATH_CONSTANT(cbrt_pi, 1.464591887561523263020142527263790391e+00, "1.46459188756152326302014252726379039173859685562793717435725593713839364979828626614568206782035382089750397002e+00")
BOOST_DEFINE_MATH_CONSTANT(one_div_cbrt_pi, 6.827840632552956814670208331581645981e-01, "6.82784063255295681467020833158164598108367515632448804042681583118899226433403918237673501922595519865685577274e-01")
BOOST_DEFINE_MATH_CONSTANT(e, 2.718281828459045235360287471352662497e+00, "2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193e+00")
BOOST_DEFINE_MATH_CONSTANT(exp_minus_half, 6.065306597126334236037995349911804534e-01, "6.06530659712633423603799534991180453441918135487186955682892158735056519413748423998647611507989456026423789794e-01")
BOOST_DEFINE_MATH_CONSTANT(e_pow_pi, 2.314069263277926900572908636794854738e+01, "2.31406926327792690057290863679485473802661062426002119934450464095243423506904527835169719970675492196759527048e+01")
BOOST_DEFINE_MATH_CONSTANT(root_e, 1.648721270700128146848650787814163571e+00, "1.64872127070012814684865078781416357165377610071014801157507931164066102119421560863277652005636664300286663776e+00")
BOOST_DEFINE_MATH_CONSTANT(log10_e, 4.342944819032518276511289189166050822e-01, "4.34294481903251827651128918916605082294397005803666566114453783165864649208870774729224949338431748318706106745e-01")
BOOST_DEFINE_MATH_CONSTANT(one_div_log10_e, 2.302585092994045684017991454684364207e+00, "2.30258509299404568401799145468436420760110148862877297603332790096757260967735248023599720508959829834196778404e+00")
BOOST_DEFINE_MATH_CONSTANT(ln_ten, 2.302585092994045684017991454684364207e+00, "2.30258509299404568401799145468436420760110148862877297603332790096757260967735248023599720508959829834196778404e+00")
BOOST_DEFINE_MATH_CONSTANT(degree, 1.745329251994329576923690768488612713e-02, "1.74532925199432957692369076848861271344287188854172545609719144017100911460344944368224156963450948221230449251e-02")
BOOST_DEFINE_MATH_CONSTANT(radian, 5.729577951308232087679815481410517033e+01, "5.72957795130823208767981548141051703324054724665643215491602438612028471483215526324409689958511109441862233816e+01")
BOOST_DEFINE_MATH_CONSTANT(sin_one, 8.414709848078965066525023216302989996e-01, "8.41470984807896506652502321630298999622563060798371065672751709991910404391239668948639743543052695854349037908e-01")
BOOST_DEFINE_MATH_CONSTANT(cos_one, 5.403023058681397174009366074429766037e-01, "5.40302305868139717400936607442976603732310420617922227670097255381100394774471764517951856087183089343571731160e-01")
BOOST_DEFINE_MATH_CONSTANT(sinh_one, 1.175201193643801456882381850595600815e+00, "1.17520119364380145688238185059560081515571798133409587022956541301330756730432389560711745208962339184041953333e+00")
BOOST_DEFINE_MATH_CONSTANT(cosh_one, 1.543080634815243778477905620757061682e+00, "1.54308063481524377847790562075706168260152911236586370473740221471076906304922369896426472643554303558704685860e+00")
BOOST_DEFINE_MATH_CONSTANT(phi, 1.618033988749894848204586834365638117e+00, "1.61803398874989484820458683436563811772030917980576286213544862270526046281890244970720720418939113748475408808e+00")
BOOST_DEFINE_MATH_CONSTANT(ln_phi, 4.812118250596034474977589134243684231e-01, "4.81211825059603447497758913424368423135184334385660519661018168840163867608221774412009429122723474997231839958e-01")
BOOST_DEFINE_MATH_CONSTANT(one_div_ln_phi, 2.078086921235027537601322606117795767e+00, "2.07808692123502753760132260611779576774219226778328348027813992191974386928553540901445615414453604821933918634e+00")
BOOST_DEFINE_MATH_CONSTANT(euler, 5.772156649015328606065120900824024310e-01, "5.77215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749514631447250e-01")
BOOST_DEFINE_MATH_CONSTANT(one_div_euler, 1.732454714600633473583025315860829681e+00, "1.73245471460063347358302531586082968115577655226680502204843613287065531408655243008832840219409928068072365714e+00")
BOOST_DEFINE_MATH_CONSTANT(euler_sqr, 3.331779238077186743183761363552442266e-01, "3.33177923807718674318376136355244226659417140249629743150833338002265793695756669661263268631715977303039565603e-01")
BOOST_DEFINE_MATH_CONSTANT(zeta_two, 1.644934066848226436472415166646025189e+00, "1.64493406684822643647241516664602518921894990120679843773555822937000747040320087383362890061975870530400431896e+00")
BOOST_DEFINE_MATH_CONSTANT(zeta_three, 1.202056903159594285399738161511449990e+00, "1.20205690315959428539973816151144999076498629234049888179227155534183820578631309018645587360933525814619915780e+00")
BOOST_DEFINE_MATH_CONSTANT(catalan, 9.159655941772190150546035149323841107e-01, "9.15965594177219015054603514932384110774149374281672134266498119621763019776254769479356512926115106248574422619e-01")
BOOST_DEFINE_MATH_CONSTANT(glaisher, 1.282427129100622636875342568869791727e+00, "1.28242712910062263687534256886979172776768892732500119206374002174040630885882646112973649195820237439420646120e+00")
BOOST_DEFINE_MATH_CONSTANT(khinchin, 2.685452001065306445309714835481795693e+00, "2.68545200106530644530971483548179569382038229399446295305115234555721885953715200280114117493184769799515346591e+00")
BOOST_DEFINE_MATH_CONSTANT(extreme_value_skewness, 1.139547099404648657492793019389846112e+00, "1.13954709940464865749279301938984611208759979583655182472165571008524800770607068570718754688693851501894272049e+00")
BOOST_DEFINE_MATH_CONSTANT(rayleigh_skewness, 6.311106578189371381918993515442277798e-01, "6.31110657818937138191899351544227779844042203134719497658094585692926819617473725459905027032537306794400047264e-01")
BOOST_DEFINE_MATH_CONSTANT(rayleigh_kurtosis, 3.245089300687638062848660410619754415e+00, "3.24508930068763806284866041061975441541706673178920936177133764493367904540874159051490619368679348977426462633e+00")
BOOST_DEFINE_MATH_CONSTANT(rayleigh_kurtosis_excess, 2.450893006876380628486604106197544154e-01, "2.45089300687638062848660410619754415417066731789209361771337644933679045408741590514906193686793489774264626328e-01")
BOOST_DEFINE_MATH_CONSTANT(two_div_pi, 6.366197723675813430755350534900574481e-01, "6.36619772367581343075535053490057448137838582961825794990669376235587190536906140360455211065012343824291370907e-01")
BOOST_DEFINE_MATH_CONSTANT(root_two_div_pi, 7.978845608028653558798921198687637369e-01, "7.97884560802865355879892119868763736951717262329869315331851659341315851798603677002504667814613872860605117725e-01")
} // namespace constants
} // namespace math
} // namespace boost
//
// We deliberately include this *after* all the declarations above,
// that way the calculation routines can call on other constants above:
//
#include <boost/math/constants/calculate_constants.hpp>
#endif // BOOST_MATH_CONSTANTS_CONSTANTS_INCLUDED

View File

@@ -0,0 +1,163 @@
// Copyright John Maddock 2010.
// 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 once
#endif
#ifndef BOOST_MATH_CONSTANTS_INFO_INCLUDED
#define BOOST_MATH_CONSTANTS_INFO_INCLUDED
#include <boost/math/constants/constants.hpp>
#include <iostream>
#include <iomanip>
#include <typeinfo>
namespace boost{ namespace math{ namespace constants{
namespace detail{
template <class T>
const char* nameof(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
{
return typeid(T).name();
}
template <>
const char* nameof<float>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(float))
{
return "float";
}
template <>
const char* nameof<double>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(double))
{
return "double";
}
template <>
const char* nameof<long double>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(long double))
{
return "long double";
}
}
template <class T, class Policy>
void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy))
{
using detail::nameof;
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127)
#endif
os <<
"Information on the Implementation and Handling of \n"
"Mathematical Constants for Type " << nameof<T>() <<
"\n\n"
"Checking for std::numeric_limits<" << nameof<T>() << "> specialisation: " <<
(std::numeric_limits<T>::is_specialized ? "yes" : "no") << std::endl;
if(std::numeric_limits<T>::is_specialized)
{
os <<
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the radix is " << std::numeric_limits<T>::radix << ".\n";
if (std::numeric_limits<T>::radix == 2)
{
os <<
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the precision is \n" << std::numeric_limits<T>::digits << " binary digits.\n";
}
else if (std::numeric_limits<T>::radix == 10)
{
os <<
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the precision is \n" << std::numeric_limits<T>::digits10 << " decimal digits.\n";
os <<
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the precision is \n"
<< std::numeric_limits<T>::digits * 1000L /301L << " binary digits.\n"; // divide by log2(10) - about 3 bits per decimal digit.
}
else
{
os << "Unknown radix = " << std::numeric_limits<T>::radix << "\n";
}
}
typedef typename boost::math::policies::precision<T, Policy>::type precision_type;
if(precision_type::value)
{
if (std::numeric_limits<T>::radix == 2)
{
os <<
"boost::math::policies::precision<" << nameof<T>() << ", " << nameof<Policy>() << " reports that the compile time precision is \n" << precision_type::value << " binary digits.\n";
}
else if (std::numeric_limits<T>::radix == 10)
{
os <<
"boost::math::policies::precision<" << nameof<T>() << ", " << nameof<Policy>() << " reports that the compile time precision is \n" << precision_type::value << " binary digits.\n";
}
else
{
os << "Unknown radix = " << std::numeric_limits<T>::radix << "\n";
}
}
else
{
os <<
"boost::math::policies::precision<" << nameof<T>() << ", Policy> \n"
"reports that there is no compile type precision available.\n"
"boost::math::tools::digits<" << nameof<T>() << ">() \n"
"reports that the current runtime precision is \n" <<
boost::math::tools::digits<T>() << " binary digits.\n";
}
typedef typename construction_traits<T, Policy>::type construction_type;
switch(construction_type::value)
{
case 0:
os <<
"No compile time precision is available, the construction method \n"
"will be decided at runtime and results will not be cached \n"
"- this may lead to poor runtime performance.\n"
"Current runtime precision indicates that\n";
if(boost::math::tools::digits<T>() > max_string_digits)
{
os << "the constant will be recalculated on each call.\n";
}
else
{
os << "the constant will be constructed from a string on each call.\n";
}
break;
case 1:
os <<
"The constant will be constructed from a float.\n";
break;
case 2:
os <<
"The constant will be constructed from a double.\n";
break;
case 3:
os <<
"The constant will be constructed from a long double.\n";
break;
case 4:
os <<
"The constant will be constructed from a string (and the result cached).\n";
break;
default:
os <<
"The constant will be calculated (and the result cached).\n";
break;
}
os << std::endl;
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template <class T>
void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
{
print_info_on_type<T, boost::math::policies::policy<> >(os);
}
}}} // namespaces
#endif // BOOST_MATH_CONSTANTS_INFO_INCLUDED

View File

@@ -0,0 +1,600 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2014.
// Copyright John Maddock 2014.
// Copyright Paul Bristow 2014.
// 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)
//
// Implement quadruple-precision <cmath> support.
#ifndef _BOOST_CSTDFLOAT_CMATH_2014_02_15_HPP_
#define _BOOST_CSTDFLOAT_CMATH_2014_02_15_HPP_
#include <boost/math/cstdfloat/cstdfloat_types.hpp>
#include <boost/math/cstdfloat/cstdfloat_limits.hpp>
#if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
#include <cmath>
#include <stdexcept>
#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
#include <boost/throw_exception.hpp>
#if defined(_WIN32) && defined(__GNUC__)
// Several versions of Mingw and probably cygwin too have broken
// libquadmath implementations that segfault as soon as you call
// expq or any function that depends on it.
#define BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
#endif
// Here is a helper function used for raising the value of a given
// floating-point type to the power of n, where n has integral type.
namespace boost { namespace math { namespace cstdfloat { namespace detail {
template<class float_type, class integer_type>
inline float_type pown(const float_type& x, const integer_type p)
{
const bool isneg = (x < 0);
const bool isnan = (x != x);
const bool isinf = ((!isneg) ? bool(+x > (std::numeric_limits<float_type>::max)())
: bool(-x > (std::numeric_limits<float_type>::max)()));
if(isnan) { return x; }
if(isinf) { return std::numeric_limits<float_type>::quiet_NaN(); }
const bool x_is_neg = (x < 0);
const float_type abs_x = (x_is_neg ? -x : x);
if(p < static_cast<integer_type>(0))
{
if(abs_x < (std::numeric_limits<float_type>::min)())
{
return (x_is_neg ? -std::numeric_limits<float_type>::infinity()
: +std::numeric_limits<float_type>::infinity());
}
else
{
return float_type(1) / pown(x, static_cast<integer_type>(-p));
}
}
if(p == static_cast<integer_type>(0))
{
return float_type(1);
}
else
{
if(p == static_cast<integer_type>(1)) { return x; }
if(abs_x > (std::numeric_limits<float_type>::max)())
{
return (x_is_neg ? -std::numeric_limits<float_type>::infinity()
: +std::numeric_limits<float_type>::infinity());
}
if (p == static_cast<integer_type>(2)) { return (x * x); }
else if(p == static_cast<integer_type>(3)) { return ((x * x) * x); }
else if(p == static_cast<integer_type>(4)) { const float_type x2 = (x * x); return (x2 * x2); }
else
{
// The variable xn stores the binary powers of x.
float_type result(((p % integer_type(2)) != integer_type(0)) ? x : float_type(1));
float_type xn (x);
integer_type p2 = p;
while(integer_type(p2 /= 2) != integer_type(0))
{
// Square xn for each binary power.
xn *= xn;
const bool has_binary_power = (integer_type(p2 % integer_type(2)) != integer_type(0));
if(has_binary_power)
{
// Multiply the result with each binary power contained in the exponent.
result *= xn;
}
}
return result;
}
}
}
} } } } // boost::math::cstdfloat::detail
// We will now define preprocessor symbols representing quadruple-precision <cmath> functions.
#if defined(BOOST_INTEL)
#define BOOST_CSTDFLOAT_FLOAT128_LDEXP __ldexpq
#define BOOST_CSTDFLOAT_FLOAT128_FREXP __frexpq
#define BOOST_CSTDFLOAT_FLOAT128_FABS __fabsq
#define BOOST_CSTDFLOAT_FLOAT128_FLOOR __floorq
#define BOOST_CSTDFLOAT_FLOAT128_CEIL __ceilq
#if !defined(BOOST_CSTDFLOAT_FLOAT128_SQRT)
#define BOOST_CSTDFLOAT_FLOAT128_SQRT __sqrtq
#endif
#define BOOST_CSTDFLOAT_FLOAT128_TRUNC __truncq
#define BOOST_CSTDFLOAT_FLOAT128_EXP __expq
#define BOOST_CSTDFLOAT_FLOAT128_EXPM1 __expm1q
#define BOOST_CSTDFLOAT_FLOAT128_POW __powq
#define BOOST_CSTDFLOAT_FLOAT128_LOG __logq
#define BOOST_CSTDFLOAT_FLOAT128_LOG10 __log10q
#define BOOST_CSTDFLOAT_FLOAT128_SIN __sinq
#define BOOST_CSTDFLOAT_FLOAT128_COS __cosq
#define BOOST_CSTDFLOAT_FLOAT128_TAN __tanq
#define BOOST_CSTDFLOAT_FLOAT128_ASIN __asinq
#define BOOST_CSTDFLOAT_FLOAT128_ACOS __acosq
#define BOOST_CSTDFLOAT_FLOAT128_ATAN __atanq
#define BOOST_CSTDFLOAT_FLOAT128_SINH __sinhq
#define BOOST_CSTDFLOAT_FLOAT128_COSH __coshq
#define BOOST_CSTDFLOAT_FLOAT128_TANH __tanhq
#define BOOST_CSTDFLOAT_FLOAT128_ASINH __asinhq
#define BOOST_CSTDFLOAT_FLOAT128_ACOSH __acoshq
#define BOOST_CSTDFLOAT_FLOAT128_ATANH __atanhq
#define BOOST_CSTDFLOAT_FLOAT128_FMOD __fmodq
#define BOOST_CSTDFLOAT_FLOAT128_ATAN2 __atan2q
#define BOOST_CSTDFLOAT_FLOAT128_LGAMMA __lgammaq
#define BOOST_CSTDFLOAT_FLOAT128_TGAMMA __tgammaq
#elif defined(__GNUC__)
#define BOOST_CSTDFLOAT_FLOAT128_LDEXP ldexpq
#define BOOST_CSTDFLOAT_FLOAT128_FREXP frexpq
#define BOOST_CSTDFLOAT_FLOAT128_FABS fabsq
#define BOOST_CSTDFLOAT_FLOAT128_FLOOR floorq
#define BOOST_CSTDFLOAT_FLOAT128_CEIL ceilq
#if !defined(BOOST_CSTDFLOAT_FLOAT128_SQRT)
#define BOOST_CSTDFLOAT_FLOAT128_SQRT sqrtq
#endif
#define BOOST_CSTDFLOAT_FLOAT128_TRUNC truncq
#define BOOST_CSTDFLOAT_FLOAT128_POW powq
#define BOOST_CSTDFLOAT_FLOAT128_LOG logq
#define BOOST_CSTDFLOAT_FLOAT128_LOG10 log10q
#define BOOST_CSTDFLOAT_FLOAT128_SIN sinq
#define BOOST_CSTDFLOAT_FLOAT128_COS cosq
#define BOOST_CSTDFLOAT_FLOAT128_TAN tanq
#define BOOST_CSTDFLOAT_FLOAT128_ASIN asinq
#define BOOST_CSTDFLOAT_FLOAT128_ACOS acosq
#define BOOST_CSTDFLOAT_FLOAT128_ATAN atanq
#define BOOST_CSTDFLOAT_FLOAT128_FMOD fmodq
#define BOOST_CSTDFLOAT_FLOAT128_ATAN2 atan2q
#define BOOST_CSTDFLOAT_FLOAT128_LGAMMA lgammaq
#if !defined(BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS)
#define BOOST_CSTDFLOAT_FLOAT128_EXP expq
#define BOOST_CSTDFLOAT_FLOAT128_EXPM1 expm1q_internal
#define BOOST_CSTDFLOAT_FLOAT128_SINH sinhq
#define BOOST_CSTDFLOAT_FLOAT128_COSH coshq
#define BOOST_CSTDFLOAT_FLOAT128_TANH tanhq
#define BOOST_CSTDFLOAT_FLOAT128_ASINH asinhq
#define BOOST_CSTDFLOAT_FLOAT128_ACOSH acoshq
#define BOOST_CSTDFLOAT_FLOAT128_ATANH atanhq
#define BOOST_CSTDFLOAT_FLOAT128_TGAMMA tgammaq
#else // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
#define BOOST_CSTDFLOAT_FLOAT128_EXP expq_patch
#define BOOST_CSTDFLOAT_FLOAT128_SINH sinhq_patch
#define BOOST_CSTDFLOAT_FLOAT128_COSH coshq_patch
#define BOOST_CSTDFLOAT_FLOAT128_TANH tanhq_patch
#define BOOST_CSTDFLOAT_FLOAT128_ASINH asinhq_patch
#define BOOST_CSTDFLOAT_FLOAT128_ACOSH acoshq_patch
#define BOOST_CSTDFLOAT_FLOAT128_ATANH atanhq_patch
#define BOOST_CSTDFLOAT_FLOAT128_TGAMMA tgammaq_patch
#endif // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
#endif
// Implement quadruple-precision <cmath> functions in the namespace
// boost::math::cstdfloat::detail. Subsequently inject these into the
// std namespace via *using* directive.
// Begin with some forward function declarations. Also implement patches
// for compilers that have broken float128 exponential functions.
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LDEXP (boost::math::cstdfloat::detail::float_internal128_t, int) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FREXP (boost::math::cstdfloat::detail::float_internal128_t, int*) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FABS (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FLOOR (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_CEIL (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TRUNC (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_POW (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LOG10 (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SIN (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COS (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TAN (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASIN (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOS (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN (boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_FMOD (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATAN2 (boost::math::cstdfloat::detail::float_internal128_t, boost::math::cstdfloat::detail::float_internal128_t) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_LGAMMA(boost::math::cstdfloat::detail::float_internal128_t) throw();
#if !defined(BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS)
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP (boost::math::cstdfloat::detail::float_internal128_t x) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH (boost::math::cstdfloat::detail::float_internal128_t x) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) throw();
#else // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
// Forward declaration of the patched exponent function, exp(x).
inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP (boost::math::cstdfloat::detail::float_internal128_t x);
inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1 (boost::math::cstdfloat::detail::float_internal128_t x)
{
// Compute exp(x) - 1 for x small.
// Use an order-36 polynomial approximation of the exponential function
// in the range of (-ln2 < x < ln2). Scale the argument to this range
// and subsequently multiply the result by 2^n accordingly.
// Derive the polynomial coefficients with Mathematica(R) by generating
// a table of high-precision values of exp(x) in the range (-ln2 < x < ln2)
// and subsequently applying the built-in *Fit* function.
// Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/180}]
// N[%, 120]
// Fit[%, {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10, x^11, x^12,
// x^13, x^14, x^15, x^16, x^17, x^18, x^19, x^20, x^21, x^22,
// x^23, x^24, x^25, x^26, x^27, x^28, x^29, x^30, x^31, x^32,
// x^33, x^34, x^35, x^36}, x]
typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
float_type sum;
if(x > BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255))
{
sum = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x) - float_type(1);
}
else
{
// Compute the polynomial approximation of exp(alpha).
sum = (((((((((((((((((((((((((((((((((((( float_type(BOOST_FLOAT128_C(2.69291698127774166063293705964720493864630783729857438187365E-42)) * x
+ float_type(BOOST_FLOAT128_C(9.70937085471487654794114679403710456028986572118859594614033E-41))) * x
+ float_type(BOOST_FLOAT128_C(3.38715585158055097155585505318085512156885389014410753080500E-39))) * x
+ float_type(BOOST_FLOAT128_C(1.15162718532861050809222658798662695267019717760563645440433E-37))) * x
+ float_type(BOOST_FLOAT128_C(3.80039074689434663295873584133017767349635602413675471702393E-36))) * x
+ float_type(BOOST_FLOAT128_C(1.21612504934087520075905434734158045947460467096773246215239E-34))) * x
+ float_type(BOOST_FLOAT128_C(3.76998762883139753126119821241037824830069851253295480396224E-33))) * x
+ float_type(BOOST_FLOAT128_C(1.13099628863830344684998293828608215735777107850991029729440E-31))) * x
+ float_type(BOOST_FLOAT128_C(3.27988923706982293204067897468714277771890104022419696770352E-30))) * x
+ float_type(BOOST_FLOAT128_C(9.18368986379558482800593745627556950089950023355628325088207E-29))) * x
+ float_type(BOOST_FLOAT128_C(2.47959626322479746949155352659617642905315302382639380521497E-27))) * x
+ float_type(BOOST_FLOAT128_C(6.44695028438447337900255966737803112935639344283098705091949E-26))) * x
+ float_type(BOOST_FLOAT128_C(1.61173757109611834904452725462599961406036904573072897122957E-24))) * x
+ float_type(BOOST_FLOAT128_C(3.86817017063068403772269360016918092488847584660382953555804E-23))) * x
+ float_type(BOOST_FLOAT128_C(8.89679139245057328674891109315654704307721758924206107351744E-22))) * x
+ float_type(BOOST_FLOAT128_C(1.95729410633912612308475595397946731738088422488032228717097E-20))) * x
+ float_type(BOOST_FLOAT128_C(4.11031762331216485847799061511674191805055663711439605760231E-19))) * x
+ float_type(BOOST_FLOAT128_C(8.22063524662432971695598123977873600603370758794431071426640E-18))) * x
+ float_type(BOOST_FLOAT128_C(1.56192069685862264622163643500633782667263448653185159383285E-16))) * x
+ float_type(BOOST_FLOAT128_C(2.81145725434552076319894558300988749849555291507956994126835E-15))) * x
+ float_type(BOOST_FLOAT128_C(4.77947733238738529743820749111754320727153728139716409114011E-14))) * x
+ float_type(BOOST_FLOAT128_C(7.64716373181981647590113198578807092707697416852226691068627E-13))) * x
+ float_type(BOOST_FLOAT128_C(1.14707455977297247138516979786821056670509688396295740818677E-11))) * x
+ float_type(BOOST_FLOAT128_C(1.60590438368216145993923771701549479323291461578567184216302E-10))) * x
+ float_type(BOOST_FLOAT128_C(2.08767569878680989792100903212014323125428376052986408239620E-09))) * x
+ float_type(BOOST_FLOAT128_C(2.50521083854417187750521083854417187750523408006206780016659E-08))) * x
+ float_type(BOOST_FLOAT128_C(2.75573192239858906525573192239858906525573195144226062684604E-07))) * x
+ float_type(BOOST_FLOAT128_C(2.75573192239858906525573192239858906525573191310049321957902E-06))) * x
+ float_type(BOOST_FLOAT128_C(0.00002480158730158730158730158730158730158730158730149317774))) * x
+ float_type(BOOST_FLOAT128_C(0.00019841269841269841269841269841269841269841269841293575920))) * x
+ float_type(BOOST_FLOAT128_C(0.00138888888888888888888888888888888888888888888888889071045))) * x
+ float_type(BOOST_FLOAT128_C(0.00833333333333333333333333333333333333333333333333332986595))) * x
+ float_type(BOOST_FLOAT128_C(0.04166666666666666666666666666666666666666666666666666664876))) * x
+ float_type(BOOST_FLOAT128_C(0.16666666666666666666666666666666666666666666666666666669048))) * x
+ float_type(BOOST_FLOAT128_C(0.50000000000000000000000000000000000000000000000000000000006))) * x
+ float_type(BOOST_FLOAT128_C(0.99999999999999999999999999999999999999999999999999999999995))) * x);
}
return sum;
}
inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP (boost::math::cstdfloat::detail::float_internal128_t x)
{
// Patch the expq() function for a subset of broken GCC compilers
// like GCC 4.7, 4.8 on MinGW.
// Use an order-36 polynomial approximation of the exponential function
// in the range of (-ln2 < x < ln2). Scale the argument to this range
// and subsequently multiply the result by 2^n accordingly.
// Derive the polynomial coefficients with Mathematica(R) by generating
// a table of high-precision values of exp(x) in the range (-ln2 < x < ln2)
// and subsequently applying the built-in *Fit* function.
// Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/180}]
// N[%, 120]
// Fit[%, {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10, x^11, x^12,
// x^13, x^14, x^15, x^16, x^17, x^18, x^19, x^20, x^21, x^22,
// x^23, x^24, x^25, x^26, x^27, x^28, x^29, x^30, x^31, x^32,
// x^33, x^34, x^35, x^36}, x]
typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
// Scale the argument x to the range (-ln2 < x < ln2).
BOOST_CONSTEXPR_OR_CONST float_type one_over_ln2 = float_type(BOOST_FLOAT128_C(1.44269504088896340735992468100189213742664595415299));
const float_type x_over_ln2 = x * one_over_ln2;
boost::int_fast32_t n;
if(x != x)
{
// The argument is NaN.
return std::numeric_limits<float_type>::quiet_NaN();
}
else if(::BOOST_CSTDFLOAT_FLOAT128_FABS(x) > BOOST_FLOAT128_C(+0.693147180559945309417232121458176568075500134360255))
{
// The absolute value of the argument exceeds ln2.
n = static_cast<boost::int_fast32_t>(::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x_over_ln2));
}
else if(::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < BOOST_FLOAT128_C(+0.693147180559945309417232121458176568075500134360255))
{
// The absolute value of the argument is less than ln2.
n = static_cast<boost::int_fast32_t>(0);
}
else
{
// The absolute value of the argument is exactly equal to ln2 (in the sense of floating-point equality).
return float_type(2);
}
// Check if the argument is very near an integer.
const float_type floor_of_x = ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x);
if(::BOOST_CSTDFLOAT_FLOAT128_FABS(x - floor_of_x) < float_type(BOOST_CSTDFLOAT_FLOAT128_EPS))
{
// Return e^n for arguments very near an integer.
return boost::math::cstdfloat::detail::pown(BOOST_FLOAT128_C(2.71828182845904523536028747135266249775724709369996), static_cast<boost::int_fast32_t>(floor_of_x));
}
// Compute the scaled argument alpha.
const float_type alpha = x - (n * BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255));
// Compute the polynomial approximation of expm1(alpha) and add to it
// in order to obtain the scaled result.
const float_type scaled_result = ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(alpha) + float_type(1);
// Rescale the result and return it.
return scaled_result * boost::math::cstdfloat::detail::pown(float_type(2), n);
}
inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH (boost::math::cstdfloat::detail::float_internal128_t x)
{
// Patch the sinhq() function for a subset of broken GCC compilers
// like GCC 4.7, 4.8 on MinGW.
typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
// Here, we use the following:
// Set: ex = exp(x)
// Set: em1 = expm1(x)
// Then
// sinh(x) = (ex - 1/ex) / 2 ; for |x| >= 1
// sinh(x) = (2em1 + em1^2) / (2ex) ; for |x| < 1
const float_type ex = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x);
if(::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < float_type(+1))
{
const float_type em1 = ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(x);
return ((em1 * 2) + (em1 * em1)) / (ex * 2);
}
else
{
return (ex - (float_type(1) / ex)) / 2;
}
}
inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH (boost::math::cstdfloat::detail::float_internal128_t x)
{
// Patch the coshq() function for a subset of broken GCC compilers
// like GCC 4.7, 4.8 on MinGW.
typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
const float_type ex = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x);
return (ex + (float_type(1) / ex)) / 2;
}
inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TANH (boost::math::cstdfloat::detail::float_internal128_t x)
{
// Patch the tanhq() function for a subset of broken GCC compilers
// like GCC 4.7, 4.8 on MinGW.
typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
const float_type ex_plus = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x);
const float_type ex_minus = (float_type(1) / ex_plus);
return (ex_plus - ex_minus) / (ex_plus + ex_minus);
}
inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ASINH(boost::math::cstdfloat::detail::float_internal128_t x) throw()
{
// Patch the asinh() function since quadmath does not have it.
typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x + ::BOOST_CSTDFLOAT_FLOAT128_SQRT((x * x) + float_type(1)));
}
inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ACOSH(boost::math::cstdfloat::detail::float_internal128_t x) throw()
{
// Patch the acosh() function since quadmath does not have it.
typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
const float_type zp(x + float_type(1));
const float_type zm(x - float_type(1));
return ::BOOST_CSTDFLOAT_FLOAT128_LOG(x + (zp * ::BOOST_CSTDFLOAT_FLOAT128_SQRT(zm / zp)));
}
inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_ATANH(boost::math::cstdfloat::detail::float_internal128_t x) throw()
{
// Patch the atanh() function since quadmath does not have it.
typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
return ( ::BOOST_CSTDFLOAT_FLOAT128_LOG(float_type(1) + x)
- ::BOOST_CSTDFLOAT_FLOAT128_LOG(float_type(1) - x)) / 2;
}
inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_TGAMMA(boost::math::cstdfloat::detail::float_internal128_t x) throw()
{
// Patch the tgammaq() function for a subset of broken GCC compilers
// like GCC 4.7, 4.8 on MinGW.
typedef boost::math::cstdfloat::detail::float_internal128_t float_type;
if(x > float_type(0))
{
return ::BOOST_CSTDFLOAT_FLOAT128_EXP(::BOOST_CSTDFLOAT_FLOAT128_LGAMMA(x));
}
else if(x < float_type(0))
{
// For x < 0, compute tgamma(-x) and use the reflection formula.
const float_type positive_x = -x;
float_type gamma_value = ::BOOST_CSTDFLOAT_FLOAT128_TGAMMA(positive_x);
const float_type floor_of_positive_x = ::BOOST_CSTDFLOAT_FLOAT128_FLOOR (positive_x);
// Take the reflection checks (slightly adapted) from <boost/math/gamma.hpp>.
const bool floor_of_z_is_equal_to_z = (positive_x == ::BOOST_CSTDFLOAT_FLOAT128_FLOOR(positive_x));
BOOST_CONSTEXPR_OR_CONST float_type my_pi = BOOST_FLOAT128_C(3.14159265358979323846264338327950288419716939937511);
if(floor_of_z_is_equal_to_z)
{
const bool is_odd = ((boost::int32_t(floor_of_positive_x) % boost::int32_t(2)) != boost::int32_t(0));
return (is_odd ? -std::numeric_limits<float_type>::infinity()
: +std::numeric_limits<float_type>::infinity());
}
const float_type sinpx_value = x * ::BOOST_CSTDFLOAT_FLOAT128_SIN(my_pi * x);
gamma_value *= sinpx_value;
const bool result_is_too_large_to_represent = ( (::BOOST_CSTDFLOAT_FLOAT128_FABS(gamma_value) < float_type(1))
&& (((std::numeric_limits<float_type>::max)() * ::BOOST_CSTDFLOAT_FLOAT128_FABS(gamma_value)) < my_pi));
if(result_is_too_large_to_represent)
{
const bool is_odd = ((boost::int32_t(floor_of_positive_x) % boost::int32_t(2)) != boost::int32_t(0));
return (is_odd ? -std::numeric_limits<float_type>::infinity()
: +std::numeric_limits<float_type>::infinity());
}
gamma_value = -my_pi / gamma_value;
if((gamma_value > float_type(0)) || (gamma_value < float_type(0)))
{
return gamma_value;
}
else
{
// The value of gamma is too small to represent. Return 0.0 here.
return float_type(0);
}
}
else
{
// Gamma of zero is complex infinity. Return NaN here.
return std::numeric_limits<float_type>::quiet_NaN();
}
}
#endif // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS
// Define the quadruple-precision <cmath> functions in the namespace boost::math::cstdfloat::detail.
namespace boost { namespace math { namespace cstdfloat { namespace detail {
inline boost::math::cstdfloat::detail::float_internal128_t ldexp (boost::math::cstdfloat::detail::float_internal128_t x, int n) { return ::BOOST_CSTDFLOAT_FLOAT128_LDEXP (x, n); }
inline boost::math::cstdfloat::detail::float_internal128_t frexp (boost::math::cstdfloat::detail::float_internal128_t x, int* pn) { return ::BOOST_CSTDFLOAT_FLOAT128_FREXP (x, pn); }
inline boost::math::cstdfloat::detail::float_internal128_t fabs (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS (x); }
inline boost::math::cstdfloat::detail::float_internal128_t abs (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FABS (x); }
inline boost::math::cstdfloat::detail::float_internal128_t floor (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_FLOOR (x); }
inline boost::math::cstdfloat::detail::float_internal128_t ceil (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_CEIL (x); }
inline boost::math::cstdfloat::detail::float_internal128_t sqrt (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT (x); }
inline boost::math::cstdfloat::detail::float_internal128_t trunc (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TRUNC (x); }
inline boost::math::cstdfloat::detail::float_internal128_t exp (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_EXP (x); }
inline boost::math::cstdfloat::detail::float_internal128_t pow (boost::math::cstdfloat::detail::float_internal128_t x, boost::math::cstdfloat::detail::float_internal128_t a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW (x, a); }
inline boost::math::cstdfloat::detail::float_internal128_t pow (boost::math::cstdfloat::detail::float_internal128_t x, int a) { return ::BOOST_CSTDFLOAT_FLOAT128_POW (x, boost::math::cstdfloat::detail::float_internal128_t(a)); }
inline boost::math::cstdfloat::detail::float_internal128_t log (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG (x); }
inline boost::math::cstdfloat::detail::float_internal128_t log10 (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LOG10 (x); }
inline boost::math::cstdfloat::detail::float_internal128_t sin (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SIN (x); }
inline boost::math::cstdfloat::detail::float_internal128_t cos (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COS (x); }
inline boost::math::cstdfloat::detail::float_internal128_t tan (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TAN (x); }
inline boost::math::cstdfloat::detail::float_internal128_t asin (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASIN (x); }
inline boost::math::cstdfloat::detail::float_internal128_t acos (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOS (x); }
inline boost::math::cstdfloat::detail::float_internal128_t atan (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN (x); }
inline boost::math::cstdfloat::detail::float_internal128_t sinh (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_SINH (x); }
inline boost::math::cstdfloat::detail::float_internal128_t cosh (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_COSH (x); }
inline boost::math::cstdfloat::detail::float_internal128_t tanh (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TANH (x); }
inline boost::math::cstdfloat::detail::float_internal128_t asinh (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ASINH (x); }
inline boost::math::cstdfloat::detail::float_internal128_t acosh (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ACOSH (x); }
inline boost::math::cstdfloat::detail::float_internal128_t atanh (boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATANH (x); }
inline boost::math::cstdfloat::detail::float_internal128_t fmod (boost::math::cstdfloat::detail::float_internal128_t a, boost::math::cstdfloat::detail::float_internal128_t b) { return ::BOOST_CSTDFLOAT_FLOAT128_FMOD (a, b); }
inline boost::math::cstdfloat::detail::float_internal128_t atan2 (boost::math::cstdfloat::detail::float_internal128_t y, boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_ATAN2 (y, x); }
inline boost::math::cstdfloat::detail::float_internal128_t lgamma(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_LGAMMA(x); }
inline boost::math::cstdfloat::detail::float_internal128_t tgamma(boost::math::cstdfloat::detail::float_internal128_t x) { return ::BOOST_CSTDFLOAT_FLOAT128_TGAMMA(x); }
} } } } // boost::math::cstdfloat::detail
// We will now inject the quadruple-precision <cmath> functions
// into the std namespace. This is done via *using* directive.
namespace std
{
using boost::math::cstdfloat::detail::ldexp;
using boost::math::cstdfloat::detail::frexp;
using boost::math::cstdfloat::detail::fabs;
using boost::math::cstdfloat::detail::abs;
using boost::math::cstdfloat::detail::floor;
using boost::math::cstdfloat::detail::ceil;
using boost::math::cstdfloat::detail::sqrt;
using boost::math::cstdfloat::detail::trunc;
using boost::math::cstdfloat::detail::exp;
using boost::math::cstdfloat::detail::pow;
using boost::math::cstdfloat::detail::log;
using boost::math::cstdfloat::detail::log10;
using boost::math::cstdfloat::detail::sin;
using boost::math::cstdfloat::detail::cos;
using boost::math::cstdfloat::detail::tan;
using boost::math::cstdfloat::detail::asin;
using boost::math::cstdfloat::detail::acos;
using boost::math::cstdfloat::detail::atan;
using boost::math::cstdfloat::detail::sinh;
using boost::math::cstdfloat::detail::cosh;
using boost::math::cstdfloat::detail::tanh;
using boost::math::cstdfloat::detail::asinh;
using boost::math::cstdfloat::detail::acosh;
using boost::math::cstdfloat::detail::atanh;
using boost::math::cstdfloat::detail::fmod;
using boost::math::cstdfloat::detail::atan2;
using boost::math::cstdfloat::detail::lgamma;
using boost::math::cstdfloat::detail::tgamma;
} // namespace std
// We will now remove the preprocessor symbols representing quadruple-precision <cmath>
// functions from the preprocessor.
#undef BOOST_CSTDFLOAT_FLOAT128_LDEXP
#undef BOOST_CSTDFLOAT_FLOAT128_FREXP
#undef BOOST_CSTDFLOAT_FLOAT128_FABS
#undef BOOST_CSTDFLOAT_FLOAT128_FLOOR
#undef BOOST_CSTDFLOAT_FLOAT128_CEIL
#undef BOOST_CSTDFLOAT_FLOAT128_SQRT
#undef BOOST_CSTDFLOAT_FLOAT128_TRUNC
#undef BOOST_CSTDFLOAT_FLOAT128_EXP
#undef BOOST_CSTDFLOAT_FLOAT128_EXPM1
#undef BOOST_CSTDFLOAT_FLOAT128_POW
#undef BOOST_CSTDFLOAT_FLOAT128_LOG
#undef BOOST_CSTDFLOAT_FLOAT128_LOG10
#undef BOOST_CSTDFLOAT_FLOAT128_SIN
#undef BOOST_CSTDFLOAT_FLOAT128_COS
#undef BOOST_CSTDFLOAT_FLOAT128_TAN
#undef BOOST_CSTDFLOAT_FLOAT128_ASIN
#undef BOOST_CSTDFLOAT_FLOAT128_ACOS
#undef BOOST_CSTDFLOAT_FLOAT128_ATAN
#undef BOOST_CSTDFLOAT_FLOAT128_SINH
#undef BOOST_CSTDFLOAT_FLOAT128_COSH
#undef BOOST_CSTDFLOAT_FLOAT128_TANH
#undef BOOST_CSTDFLOAT_FLOAT128_ASINH
#undef BOOST_CSTDFLOAT_FLOAT128_ACOSH
#undef BOOST_CSTDFLOAT_FLOAT128_ATANH
#undef BOOST_CSTDFLOAT_FLOAT128_FMOD
#undef BOOST_CSTDFLOAT_FLOAT128_ATAN2
#undef BOOST_CSTDFLOAT_FLOAT128_LGAMMA
#undef BOOST_CSTDFLOAT_FLOAT128_TGAMMA
#endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
#endif // _BOOST_CSTDFLOAT_CMATH_2014_02_15_HPP_

View File

@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2014.
// Copyright John Maddock 2014.
// Copyright Paul Bristow 2014.
// 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)
//
// Implement quadruple-precision (and extended) support for <complex>.
#ifndef _BOOST_CSTDFLOAT_COMPLEX_2014_02_15_HPP_
#define _BOOST_CSTDFLOAT_COMPLEX_2014_02_15_HPP_
#include <boost/math/cstdfloat/cstdfloat_types.hpp>
#include <boost/math/cstdfloat/cstdfloat_limits.hpp>
#include <boost/math/cstdfloat/cstdfloat_cmath.hpp>
#include <boost/math/cstdfloat/cstdfloat_iostream.hpp>
#if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS)
#error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_LIMITS defined.
#endif
#if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH)
#error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH defined.
#endif
#if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_IOSTREAM)
#error You can not use <boost/math/cstdfloat/cstdfloat_complex.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_IOSTREAM defined.
#endif
#if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
#define BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE boost::math::cstdfloat::detail::float_internal128_t
#include <boost/math/cstdfloat/cstdfloat_complex_std.hpp>
#undef BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE
#endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
#endif // _BOOST_CSTDFLOAT_COMPLEX_2014_02_15_HPP_

View File

@@ -0,0 +1,641 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2014.
// Copyright John Maddock 2014.
// Copyright Paul Bristow 2014.
// 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)
//
// Implement a specialization of std::complex<> for *anything* that
// is defined as BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE.
#ifndef _BOOST_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_
#define _BOOST_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_
#if defined(__GNUC__)
#pragma GCC system_header
#endif
#include <complex>
#include <boost/math/constants/constants.hpp>
namespace std
{
// Forward declarations.
template<class float_type>
class complex;
template<>
class complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>;
inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE real(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE imag(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE abs (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE arg (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE norm(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> conj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> proj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> polar(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&,
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& = 0);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sqrt (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sin (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cos (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tan (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asin (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acos (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atan (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> exp (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log10(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&,
int);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&,
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&,
const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow (const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE&,
const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sinh (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cosh (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tanh (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asinh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acosh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atanh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
template<class char_type, class traits_type>
inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>&, const std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
template<class char_type, class traits_type>
inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>&, std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>&);
// Template specialization of the complex class.
template<>
class complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>
{
public:
typedef BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE value_type;
explicit complex(const complex<float>&);
explicit complex(const complex<double>&);
explicit complex(const complex<long double>&);
#if defined(BOOST_NO_CXX11_CONSTEXPR)
complex(const value_type& r = value_type(),
const value_type& i = value_type()) : re(r),
im(i) { }
template<typename X>
complex(const complex<X>& x) : re(x.real()),
im(x.imag()) { }
const value_type& real() const { return re; }
const value_type& imag() const { return im; }
value_type& real() { return re; }
value_type& imag() { return im; }
#else
BOOST_CONSTEXPR complex(const value_type& r = value_type(),
const value_type& i = value_type()) : re(r),
im(i) { }
template<typename X>
BOOST_CONSTEXPR complex(const complex<X>& x) : re(x.real()),
im(x.imag()) { }
value_type real() const { return re; }
value_type imag() const { return im; }
#endif
void real(value_type r) { re = r; }
void imag(value_type i) { im = i; }
complex<value_type>& operator=(const value_type& v)
{
re = v;
im = value_type(0);
return *this;
}
complex<value_type>& operator+=(const value_type& v)
{
re += v;
return *this;
}
complex<value_type>& operator-=(const value_type& v)
{
re -= v;
return *this;
}
complex<value_type>& operator*=(const value_type& v)
{
re *= v;
im *= v;
return *this;
}
complex<value_type>& operator/=(const value_type& v)
{
re /= v;
im /= v;
return *this;
}
template<typename X>
complex<value_type>& operator=(const complex<X>& x)
{
re = x.real();
im = x.imag();
return *this;
}
template<typename X>
complex<value_type>& operator+=(const complex<X>& x)
{
re += x.real();
im += x.imag();
return *this;
}
template<typename X>
complex<value_type>& operator-=(const complex<X>& x)
{
re -= x.real();
im -= x.imag();
return *this;
}
template<typename X>
complex<value_type>& operator*=(const complex<X>& x)
{
const value_type tmp_real = (re * x.real()) - (im * x.imag());
im = (re * x.imag()) + (im * x.real());
re = tmp_real;
return *this;
}
template<typename X>
complex<value_type>& operator/=(const complex<X>& x)
{
const value_type tmp_real = (re * x.real()) + (im * x.imag());
const value_type the_norm = std::norm(x);
im = ((im * x.real()) - (re * x.imag())) / the_norm;
re = tmp_real / the_norm;
return *this;
}
private:
value_type re;
value_type im;
};
// Constructors from built-in complex representation of floating-point types.
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<float>& f) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( f.imag())) { }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<double>& d) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE( d.imag())) { }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::complex(const complex<long double>& ld) : re(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.real())), im(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(ld.imag())) { }
} // namespace std
namespace boost { namespace math { namespace cstdfloat { namespace detail {
template<class float_type> inline std::complex<float_type> multiply_by_i(const std::complex<float_type>& x)
{
// Multiply x (in C) by I (the imaginary component), and return the result.
return std::complex<float_type>(-x.imag(), x.real());
}
} } } } // boost::math::cstdfloat::detail
namespace std
{
// ISO/IEC 14882:2011, Section 26.4.7, specific values.
inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE real(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return x.real(); }
inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE imag(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return x.imag(); }
inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE abs (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { using std::sqrt; return sqrt ((real(x) * real(x)) + (imag(x) * imag(x))); }
inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE arg (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { using std::atan2; return atan2(x.imag(), x.real()); }
inline BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE norm(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return (real(x) * real(x)) + (imag(x) * imag(x)); }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> conj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(x.real(), -x.imag()); }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> proj (const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE m = (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)();
if ((x.real() > m)
|| (x.real() < -m)
|| (x.imag() > m)
|| (x.imag() < -m))
{
// We have an infinity, return a normalized infinity, respecting the sign of the imaginary part:
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(), x.imag() < 0 ? -0 : 0);
}
return x;
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> polar(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& rho,
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& theta)
{
using std::sin;
using std::cos;
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(rho * cos(theta), rho * sin(theta));
}
// Global add, sub, mul, div.
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() + v.real(), u.imag() + v.imag()); }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() - v.real(), u.imag() - v.imag()); }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator*(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v)
{
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>((u.real() * v.real()) - (u.imag() * v.imag()),
(u.real() * v.imag()) + (u.imag() * v.real()));
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator/(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v)
{
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE the_norm = std::norm(v);
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(((u.real() * v.real()) + (u.imag() * v.imag())) / the_norm,
((u.imag() * v.real()) - (u.real() * v.imag())) / the_norm);
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() + v, u.imag()); }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() - v, u.imag()); }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator*(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() * v, u.imag() * v); }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator/(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u.real() / v, u.imag() / v); }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u + v.real(), v.imag()); }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u - v.real(), -v.imag()); }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator*(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(u * v.real(), u * v.imag()); }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator/(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& u, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& v) { const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE v_norm = norm(v); return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>((u * v.real()) / v_norm, (-u * v.imag()) / v_norm); }
// Unary plus / minus.
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator+(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u) { return u; }
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> operator-(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& u) { return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(-u.real(), -u.imag()); }
// Equality and inequality.
inline bool operator==(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x.real() == y.real()) && (x.imag() == y.imag())); }
inline bool operator==(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& y) { return ((x.real() == y) && (x.imag() == BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); }
inline bool operator==(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x == y.real()) && (y.imag() == BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); }
inline bool operator!=(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x.real() != y.real()) || (x.imag() != y.imag())); }
inline bool operator!=(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x, const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& y) { return ((x.real() != y) || (x.imag() != BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); }
inline bool operator!=(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x, const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& y) { return ((x != y.real()) || (y.imag() != BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(0))); }
// ISO/IEC 14882:2011, Section 26.4.8, transcendentals.
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sqrt(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
using std::fabs;
using std::sqrt;
// Compute sqrt(x) for x in C:
// sqrt(x) = (s , xi / 2s) : for xr > 0,
// (|xi| / 2s, +-s) : for xr < 0,
// (sqrt(xi), sqrt(xi) : for xr = 0,
// where s = sqrt{ [ |xr| + sqrt(xr^2 + xi^2) ] / 2 },
// and the +- sign is the same as the sign of xi.
if(x.real() > 0)
{
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE s = sqrt((fabs(x.real()) + std::abs(x)) / 2);
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(s, x.imag() / (s * 2));
}
else if(x.real() < 0)
{
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE s = sqrt((fabs(x.real()) + std::abs(x)) / 2);
const bool imag_is_neg = (x.imag() < 0);
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(fabs(x.imag()) / (s * 2), (imag_is_neg ? -s : s));
}
else
{
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sqrt_xi_half = sqrt(x.imag() / 2);
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(sqrt_xi_half, sqrt_xi_half);
}
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sin(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
using std::sin;
using std::cos;
using std::exp;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2;
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(sin_x * cosh_y, cos_x * sinh_y);
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cos(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
using std::sin;
using std::cos;
using std::exp;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2;
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_x * cosh_y, -(sin_x * sinh_y));
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tan(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
using std::sin;
using std::cos;
using std::exp;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_x = sin (x.real());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_x = cos (x.real());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_yp = exp (x.imag());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_ym = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_yp;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_y = (exp_yp - exp_ym) / 2;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_y = (exp_yp + exp_ym) / 2;
return ( complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(sin_x * cosh_y, cos_x * sinh_y)
/ complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_x * cosh_y, -sin_x * sinh_y));
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asin(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
return -boost::math::cstdfloat::detail::multiply_by_i(std::log(boost::math::cstdfloat::detail::multiply_by_i(x) + std::sqrt(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - (x * x))));
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acos(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
return boost::math::constants::half_pi<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>() - std::asin(x);
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atan(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> izz = boost::math::cstdfloat::detail::multiply_by_i(x);
return boost::math::cstdfloat::detail::multiply_by_i(std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - izz) - std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) + izz)) / 2;
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> exp(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
using std::exp;
return std::polar(exp(x.real()), x.imag());
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
using std::atan2;
using std::log;
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(log(std::norm(x)) / 2, atan2(x.imag(), x.real()));
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> log10(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
return std::log(x) / boost::math::constants::ln_ten<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>();
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x,
int p)
{
const bool re_isneg = (x.real() < 0);
const bool re_isnan = (x.real() != x.real());
const bool re_isinf = ((!re_isneg) ? bool(+x.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
: bool(-x.real() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()));
const bool im_isneg = (x.imag() < 0);
const bool im_isnan = (x.imag() != x.imag());
const bool im_isinf = ((!im_isneg) ? bool(+x.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
: bool(-x.imag() > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)()));
if(re_isnan || im_isnan) { return x; }
if(re_isinf || im_isinf)
{
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN(),
std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::quiet_NaN());
}
if(p < 0)
{
if(std::abs(x) < (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::min)())
{
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity(),
std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity());
}
else
{
return BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / std::pow(x, -p);
}
}
if(p == 0)
{
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1));
}
else
{
if(p == 1) { return x; }
if(std::abs(x) > (std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::max)())
{
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE re = (re_isneg ? -std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity()
: +std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE im = (im_isneg ? -std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity()
: +std::numeric_limits<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>::infinity());
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(re, im);
}
if (p == 2) { return (x * x); }
else if(p == 3) { return ((x * x) * x); }
else if(p == 4) { const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> x2 = (x * x); return (x2 * x2); }
else
{
// The variable xn stores the binary powers of x.
complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> result(((p % 2) != 0) ? x : complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1)));
complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> xn (x);
int p2 = p;
while((p2 /= 2) != 0)
{
// Square xn for each binary power.
xn *= xn;
const bool has_binary_power = ((p2 % 2) != 0);
if(has_binary_power)
{
// Multiply the result with each binary power contained in the exponent.
result *= xn;
}
}
return result;
}
}
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x,
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& a)
{
return std::exp(a * std::log(x));
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x,
const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& a)
{
return std::exp(a * std::log(x));
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> pow(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& x,
const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& a)
{
return std::exp(a * std::log(x));
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> sinh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
using std::sin;
using std::cos;
using std::exp;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_y = sin (x.imag());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_y = cos (x.imag());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xp = exp (x.real());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xm = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_xp;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_x = (exp_xp - exp_xm) / 2;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_x = (exp_xp + exp_xm) / 2;
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_y * sinh_x, cosh_x * sin_y);
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> cosh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
using std::sin;
using std::cos;
using std::exp;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sin_y = sin (x.imag());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cos_y = cos (x.imag());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xp = exp (x.real());
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE exp_xm = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / exp_xp;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE sinh_x = (exp_xp - exp_xm) / 2;
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE cosh_x = (exp_xp + exp_xm) / 2;
return complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(cos_y * cosh_x, sin_y * sinh_x);
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> tanh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> ex_plus = std::exp(x);
const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> ex_minus = BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) / ex_plus;
return (ex_plus - ex_minus) / (ex_plus + ex_minus);
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> asinh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
return std::log(x + std::sqrt((x * x) + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1)));
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> acosh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE my_one(1);
const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> zp(x.real() + my_one, x.imag());
const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> zm(x.real() - my_one, x.imag());
return std::log(x + (zp * std::sqrt(zm / zp)));
}
inline complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE> atanh(const complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
return (std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) + x) - std::log(BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1) - x)) / 2.0;
}
template<class char_type, class traits_type>
inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>& os, const std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
std::basic_ostringstream<char_type, traits_type> ostr;
ostr.flags(os.flags());
ostr.imbue(os.getloc());
ostr.precision(os.precision());
ostr << char_type('(')
<< x.real()
<< char_type(',')
<< x.imag()
<< char_type(')');
return (os << ostr.str());
}
template<class char_type, class traits_type>
inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>& is, std::complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>& x)
{
BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE rx;
BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE ix;
char_type the_char;
static_cast<void>(is >> the_char);
if(the_char == static_cast<char_type>('('))
{
static_cast<void>(is >> rx >> the_char);
if(the_char == static_cast<char_type>(','))
{
static_cast<void>(is >> ix >> the_char);
if(the_char == static_cast<char_type>(')'))
{
x = complex<BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE>(rx, ix);
}
else
{
is.setstate(ios_base::failbit);
}
}
else if(the_char == static_cast<char_type>(')'))
{
x = rx;
}
else
{
is.setstate(ios_base::failbit);
}
}
else
{
static_cast<void>(is.putback(the_char));
static_cast<void>(is >> rx);
x = rx;
}
return is;
}
} // namespace std
#endif // _BOOST_CSTDFLOAT_COMPLEX_STD_2014_02_15_HPP_

View File

@@ -0,0 +1,774 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2014.
// Copyright John Maddock 2014.
// Copyright Paul Bristow 2014.
// 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)
//
// Implement quadruple-precision I/O stream operations.
#ifndef _BOOST_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
#define _BOOST_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_
#include <boost/math/cstdfloat/cstdfloat_types.hpp>
#include <boost/math/cstdfloat/cstdfloat_limits.hpp>
#include <boost/math/cstdfloat/cstdfloat_cmath.hpp>
#if defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH)
#error You can not use <boost/math/cstdfloat/cstdfloat_iostream.hpp> with BOOST_CSTDFLOAT_NO_LIBQUADMATH_CMATH defined.
#endif
#if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
#include <cstddef>
#include <istream>
#include <ostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <boost/static_assert.hpp>
#include <boost/throw_exception.hpp>
// #if (0)
#if defined(__GNUC__)
// Forward declarations of quadruple-precision string functions.
extern "C" int quadmath_snprintf(char *str, size_t size, const char *format, ...) throw();
extern "C" boost::math::cstdfloat::detail::float_internal128_t strtoflt128(const char*, char **) throw();
namespace std
{
template<typename char_type, class traits_type>
inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>& os, const boost::math::cstdfloat::detail::float_internal128_t& x)
{
std::basic_ostringstream<char_type, traits_type> ostr;
ostr.flags(os.flags());
ostr.imbue(os.getloc());
ostr.precision(os.precision());
char my_buffer[64U];
const int my_prec = static_cast<int>(os.precision());
const int my_digits = ((my_prec == 0) ? 36 : my_prec);
const std::ios_base::fmtflags my_flags = os.flags();
char my_format_string[8U];
std::size_t my_format_string_index = 0U;
my_format_string[my_format_string_index] = '%';
++my_format_string_index;
if(my_flags & std::ios_base::showpos) { my_format_string[my_format_string_index] = '+'; ++my_format_string_index; }
if(my_flags & std::ios_base::showpoint) { my_format_string[my_format_string_index] = '#'; ++my_format_string_index; }
my_format_string[my_format_string_index + 0U] = '.';
my_format_string[my_format_string_index + 1U] = '*';
my_format_string[my_format_string_index + 2U] = 'Q';
my_format_string_index += 3U;
char the_notation_char;
if (my_flags & std::ios_base::scientific) { the_notation_char = 'e'; }
else if(my_flags & std::ios_base::fixed) { the_notation_char = 'f'; }
else { the_notation_char = 'g'; }
my_format_string[my_format_string_index + 0U] = the_notation_char;
my_format_string[my_format_string_index + 1U] = 0;
const int v = ::quadmath_snprintf(my_buffer,
static_cast<int>(sizeof(my_buffer)),
my_format_string,
my_digits,
x);
if(v < 0) { BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed internally in quadmath_snprintf().")); }
if(v >= static_cast<int>(sizeof(my_buffer) - 1U))
{
// Evidently there is a really long floating-point string here,
// such as a small decimal representation in non-scientific notation.
// So we have to use dynamic memory allocation for the output
// string buffer.
char* my_buffer2 = static_cast<char*>(0U);
#ifndef BOOST_NO_EXCEPTIONS
try
{
#endif
my_buffer2 = new char[v + 3];
#ifndef BOOST_NO_EXCEPTIONS
}
catch(const std::bad_alloc&)
{
BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed while allocating memory."));
}
#endif
const int v2 = ::quadmath_snprintf(my_buffer2,
v + 3,
my_format_string,
my_digits,
x);
if(v2 >= v + 3)
{
BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of boost::float128_t failed."));
}
static_cast<void>(ostr << my_buffer2);
delete [] my_buffer2;
}
else
{
static_cast<void>(ostr << my_buffer);
}
return (os << ostr.str());
}
template<typename char_type, class traits_type>
inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>& is, boost::math::cstdfloat::detail::float_internal128_t& x)
{
std::string str;
static_cast<void>(is >> str);
char* p_end;
x = strtoflt128(str.c_str(), &p_end);
if(static_cast<std::ptrdiff_t>(p_end - str.c_str()) != static_cast<std::ptrdiff_t>(str.length()))
{
for(std::string::const_reverse_iterator it = str.rbegin(); it != str.rend(); ++it)
{
static_cast<void>(is.putback(*it));
}
is.setstate(ios_base::failbit);
BOOST_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a boost::float128_t"));
}
return is;
}
}
// #elif defined(__GNUC__)
#elif defined(BOOST_INTEL)
// The section for I/O stream support for the ICC compiler is particularly
// long, because these functions must be painstakingly synthesized from
// manually-written routines (ICC does not support I/O stream operations
// for its _Quad type).
// The following string-extraction routines are based on the methodology
// used in Boost.Multiprecision by John Maddock and Christopher Kormanyos.
// This methodology has been slightly modified here for boost::float128_t.
#include <cstring>
#include <cctype>
#include <boost/lexical_cast.hpp>
namespace boost { namespace math { namespace cstdfloat { namespace detail {
template<class string_type>
void format_float_string(string_type& str,
int my_exp,
int digits,
const std::ios_base::fmtflags f,
const bool iszero)
{
typedef typename string_type::size_type size_type;
const bool scientific = ((f & std::ios_base::scientific) == std::ios_base::scientific);
const bool fixed = ((f & std::ios_base::fixed) == std::ios_base::fixed);
const bool showpoint = ((f & std::ios_base::showpoint) == std::ios_base::showpoint);
const bool showpos = ((f & std::ios_base::showpos) == std::ios_base::showpos);
const bool b_neg = ((str.size() != 0U) && (str[0] == '-'));
if(b_neg)
{
str.erase(0, 1);
}
if(digits == 0)
{
digits = static_cast<int>((std::max)(str.size(), size_type(16)));
}
if(iszero || str.empty() || (str.find_first_not_of('0') == string_type::npos))
{
// We will be printing zero, even though the value might not
// actually be zero (it just may have been rounded to zero).
str = "0";
if(scientific || fixed)
{
str.append(1, '.');
str.append(size_type(digits), '0');
if(scientific)
{
str.append("e+00");
}
}
else
{
if(showpoint)
{
str.append(1, '.');
if(digits > 1)
{
str.append(size_type(digits - 1), '0');
}
}
}
if(b_neg)
{
str.insert(0U, 1U, '-');
}
else if(showpos)
{
str.insert(0U, 1U, '+');
}
return;
}
if(!fixed && !scientific && !showpoint)
{
// Suppress trailing zeros.
typename string_type::iterator pos = str.end();
while(pos != str.begin() && *--pos == '0') { ; }
if(pos != str.end())
{
++pos;
}
str.erase(pos, str.end());
if(str.empty())
{
str = '0';
}
}
else if(!fixed || (my_exp >= 0))
{
// Pad out the end with zero's if we need to.
int chars = static_cast<int>(str.size());
chars = digits - chars;
if(scientific)
{
++chars;
}
if(chars > 0)
{
str.append(static_cast<size_type>(chars), '0');
}
}
if(fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
{
if((1 + my_exp) > static_cast<int>(str.size()))
{
// Just pad out the end with zeros.
str.append(static_cast<size_type>((1 + my_exp) - static_cast<int>(str.size())), '0');
if(showpoint || fixed)
{
str.append(".");
}
}
else if(my_exp + 1 < static_cast<int>(str.size()))
{
if(my_exp < 0)
{
str.insert(0U, static_cast<size_type>(-1 - my_exp), '0');
str.insert(0U, "0.");
}
else
{
// Insert the decimal point:
str.insert(static_cast<size_type>(my_exp + 1), 1, '.');
}
}
else if(showpoint || fixed) // we have exactly the digits we require to left of the point
{
str += ".";
}
if(fixed)
{
// We may need to add trailing zeros.
int l = static_cast<int>(str.find('.') + 1U);
l = digits - (static_cast<int>(str.size()) - l);
if(l > 0)
{
str.append(size_type(l), '0');
}
}
}
else
{
// Scientific format:
if(showpoint || (str.size() > 1))
{
str.insert(1U, 1U, '.');
}
str.append(1U, 'e');
string_type e = boost::lexical_cast<string_type>(std::abs(my_exp));
if(e.size() < 2U)
{
e.insert(0U, 2U - e.size(), '0');
}
if(my_exp < 0)
{
e.insert(0U, 1U, '-');
}
else
{
e.insert(0U, 1U, '+');
}
str.append(e);
}
if(b_neg)
{
str.insert(0U, 1U, '-');
}
else if(showpos)
{
str.insert(0U, 1U, '+');
}
}
template<class float_type, class type_a> inline void eval_convert_to(type_a* pa, const float_type& cb) { *pa = static_cast<type_a>(cb); }
template<class float_type, class type_a> inline void eval_add (float_type& b, const type_a& a) { b += a; }
template<class float_type, class type_a> inline void eval_subtract (float_type& b, const type_a& a) { b -= a; }
template<class float_type, class type_a> inline void eval_multiply (float_type& b, const type_a& a) { b *= a; }
template<class float_type> inline void eval_multiply (float_type& b, const float_type& cb, const float_type& cb2) { b = (cb * cb2); }
template<class float_type, class type_a> inline void eval_divide (float_type& b, const type_a& a) { b /= a; }
template<class float_type> inline void eval_log10 (float_type& b, const float_type& cb) { b = std::log10(cb); }
template<class float_type> inline void eval_floor (float_type& b, const float_type& cb) { b = std::floor(cb); }
inline void round_string_up_at(std::string& s, int pos, int& expon)
{
// This subroutine rounds up a string representation of a
// number at the given position pos.
if(pos < 0)
{
s.insert(0U, 1U, '1');
s.erase(s.size() - 1U);
++expon;
}
else if(s[pos] == '9')
{
s[pos] = '0';
round_string_up_at(s, pos - 1, expon);
}
else
{
if((pos == 0) && (s[pos] == '0') && (s.size() == 1))
{
++expon;
}
++s[pos];
}
}
template<class float_type>
std::string convert_to_string(float_type& x,
std::streamsize digits,
const std::ios_base::fmtflags f)
{
const bool isneg = (x < 0);
const bool iszero = ((!isneg) ? bool(+x < (std::numeric_limits<float_type>::min)())
: bool(-x < (std::numeric_limits<float_type>::min)()));
const bool isnan = (x != x);
const bool isinf = ((!isneg) ? bool(+x > (std::numeric_limits<float_type>::max)())
: bool(-x > (std::numeric_limits<float_type>::max)()));
int expon = 0;
if(digits <= 0) { digits = std::numeric_limits<float_type>::max_digits10; }
const int org_digits = static_cast<int>(digits);
std::string result;
if(iszero)
{
result = "0";
}
else if(isinf)
{
if(x < 0)
{
return "-inf";
}
else
{
return ((f & std::ios_base::showpos) == std::ios_base::showpos) ? "+inf" : "inf";
}
}
else if(isnan)
{
return "nan";
}
else
{
// Start by figuring out the base-10 exponent.
if(isneg) { x = -x; }
float_type t;
float_type ten = 10;
eval_log10(t, x);
eval_floor(t, t);
eval_convert_to(&expon, t);
if(-expon > std::numeric_limits<float_type>::max_exponent10 - 3)
{
int e = -expon / 2;
const float_type t2 = boost::math::cstdfloat::detail::pown(ten, e);
eval_multiply(t, t2, x);
eval_multiply(t, t2);
if((expon & 1) != 0)
{
eval_multiply(t, ten);
}
}
else
{
t = boost::math::cstdfloat::detail::pown(ten, -expon);
eval_multiply(t, x);
}
// Make sure that the value lies between [1, 10), and adjust if not.
if(t < 1)
{
eval_multiply(t, 10);
--expon;
}
else if(t >= 10)
{
eval_divide(t, 10);
++expon;
}
float_type digit;
int cdigit;
// Adjust the number of digits required based on formatting options.
if(((f & std::ios_base::fixed) == std::ios_base::fixed) && (expon != -1))
{
digits += (expon + 1);
}
if((f & std::ios_base::scientific) == std::ios_base::scientific)
{
++digits;
}
// Extract the base-10 digits one at a time.
for(int i = 0; i < digits; ++i)
{
eval_floor(digit, t);
eval_convert_to(&cdigit, digit);
result += static_cast<char>('0' + cdigit);
eval_subtract(t, digit);
eval_multiply(t, ten);
}
// Possibly round the result.
if(digits >= 0)
{
eval_floor(digit, t);
eval_convert_to(&cdigit, digit);
eval_subtract(t, digit);
if((cdigit == 5) && (t == 0))
{
// Use simple bankers rounding.
if((static_cast<int>(*result.rbegin() - '0') & 1) != 0)
{
round_string_up_at(result, static_cast<int>(result.size() - 1U), expon);
}
}
else if(cdigit >= 5)
{
round_string_up_at(result, static_cast<int>(result.size() - 1), expon);
}
}
}
while((result.size() > static_cast<std::string::size_type>(digits)) && result.size())
{
// We may get here as a result of rounding.
if(result.size() > 1U)
{
result.erase(result.size() - 1U);
}
else
{
if(expon > 0)
{
--expon; // so we put less padding in the result.
}
else
{
++expon;
}
++digits;
}
}
if(isneg)
{
result.insert(0U, 1U, '-');
}
format_float_string(result, expon, org_digits, f, iszero);
return result;
}
template <class float_type>
bool convert_from_string(float_type& value, const char* p)
{
value = 0;
if((p == static_cast<const char*>(0U)) || (*p == static_cast<char>(0)))
{
return;
}
bool is_neg = false;
bool is_neg_expon = false;
BOOST_CONSTEXPR_OR_CONST int ten = 10;
int expon = 0;
int digits_seen = 0;
BOOST_CONSTEXPR_OR_CONST int max_digits = std::numeric_limits<float_type>::max_digits10 + 1;
if(*p == static_cast<char>('+'))
{
++p;
}
else if(*p == static_cast<char>('-'))
{
is_neg = true;
++p;
}
const bool isnan = ((std::strcmp(p, "nan") == 0) || (std::strcmp(p, "NaN") == 0) || (std::strcmp(p, "NAN") == 0));
if(isnan)
{
eval_divide(value, 0);
if(is_neg)
{
value = -value;
}
return true;
}
const bool isinf = ((std::strcmp(p, "inf") == 0) || (std::strcmp(p, "Inf") == 0) || (std::strcmp(p, "INF") == 0));
if(isinf)
{
value = 1;
eval_divide(value, 0);
if(is_neg)
{
value = -value;
}
return true;
}
// Grab all the leading digits before the decimal point.
while(std::isdigit(*p))
{
eval_multiply(value, ten);
eval_add(value, static_cast<int>(*p - '0'));
++p;
++digits_seen;
}
if(*p == static_cast<char>('.'))
{
// Grab everything after the point, stop when we've seen
// enough digits, even if there are actually more available.
++p;
while(std::isdigit(*p))
{
eval_multiply(value, ten);
eval_add(value, static_cast<int>(*p - '0'));
++p;
--expon;
if(++digits_seen > max_digits)
{
break;
}
}
while(std::isdigit(*p))
{
++p;
}
}
// Parse the exponent.
if((*p == static_cast<char>('e')) || (*p == static_cast<char>('E')))
{
++p;
if(*p == static_cast<char>('+'))
{
++p;
}
else if(*p == static_cast<char>('-'))
{
is_neg_expon = true;
++p;
}
int e2 = 0;
while(std::isdigit(*p))
{
e2 *= 10;
e2 += (*p - '0');
++p;
}
if(is_neg_expon)
{
e2 = -e2;
}
expon += e2;
}
if(expon)
{
// Scale by 10^expon. Note that 10^expon can be outside the range
// of our number type, even though the result is within range.
// If that looks likely, then split the calculation in two parts.
float_type t;
t = ten;
if(expon > (std::numeric_limits<float_type>::min_exponent10 + 2))
{
t = boost::math::cstdfloat::detail::pown(t, expon);
eval_multiply(value, t);
}
else
{
t = boost::math::cstdfloat::detail::pown(t, (expon + digits_seen + 1));
eval_multiply(value, t);
t = ten;
t = boost::math::cstdfloat::detail::pown(t, (-digits_seen - 1));
eval_multiply(value, t);
}
}
if(is_neg)
{
value = -value;
}
return (*p == static_cast<char>(0));
}
} } } } // boost::math::cstdfloat::detail
namespace std
{
template<typename char_type, class traits_type>
inline std::basic_ostream<char_type, traits_type>& operator<<(std::basic_ostream<char_type, traits_type>& os, const boost::math::cstdfloat::detail::float_internal128_t& x)
{
boost::math::cstdfloat::detail::float_internal128_t non_const_x = x;
const std::string str = boost::math::cstdfloat::detail::convert_to_string(non_const_x,
os.precision(),
os.flags());
std::basic_ostringstream<char_type, traits_type> ostr;
ostr.flags(os.flags());
ostr.imbue(os.getloc());
ostr.precision(os.precision());
static_cast<void>(ostr << str);
return (os << ostr.str());
}
template<typename char_type, class traits_type>
inline std::basic_istream<char_type, traits_type>& operator>>(std::basic_istream<char_type, traits_type>& is, boost::math::cstdfloat::detail::float_internal128_t& x)
{
std::string str;
static_cast<void>(is >> str);
const bool conversion_is_ok = boost::math::cstdfloat::detail::convert_from_string(x, str.c_str());
if(false == conversion_is_ok)
{
for(std::string::const_reverse_iterator it = str.rbegin(); it != str.rend(); ++it)
{
static_cast<void>(is.putback(*it));
}
is.setstate(ios_base::failbit);
BOOST_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a boost::float128_t"));
}
return is;
}
}
#endif // Use __GNUC__ or BOOST_INTEL libquadmath
#endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
#endif // _BOOST_CSTDFLOAT_IOSTREAM_2014_02_15_HPP_

View File

@@ -0,0 +1,75 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2014.
// Copyright John Maddock 2014.
// Copyright Paul Bristow 2014.
// 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)
//
// Implement quadruple-precision std::numeric_limits<> support.
#ifndef _BOOST_CSTDFLOAT_LIMITS_2014_01_09_HPP_
#define _BOOST_CSTDFLOAT_LIMITS_2014_01_09_HPP_
#include <boost/math/cstdfloat/cstdfloat_types.hpp>
#if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
#include <limits>
// Define the name of the global quadruple-precision function to be used for
// calculating quiet_NaN() in the specialization of std::numeric_limits<>.
#if defined(BOOST_INTEL)
#define BOOST_CSTDFLOAT_FLOAT128_SQRT __sqrtq
#elif defined(__GNUC__)
#define BOOST_CSTDFLOAT_FLOAT128_SQRT sqrtq
#endif
// Forward declaration of the quadruple-precision square root function.
extern "C" boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SQRT(boost::math::cstdfloat::detail::float_internal128_t) throw();
namespace std
{
template<>
class numeric_limits<boost::math::cstdfloat::detail::float_internal128_t>
{
public:
BOOST_STATIC_CONSTEXPR bool is_specialized = true;
static boost::math::cstdfloat::detail::float_internal128_t (min) () BOOST_NOEXCEPT { return BOOST_CSTDFLOAT_FLOAT128_MIN; }
static boost::math::cstdfloat::detail::float_internal128_t (max) () BOOST_NOEXCEPT { return BOOST_CSTDFLOAT_FLOAT128_MAX; }
static boost::math::cstdfloat::detail::float_internal128_t lowest() BOOST_NOEXCEPT { return -(max)(); }
BOOST_STATIC_CONSTEXPR int digits = 113;
BOOST_STATIC_CONSTEXPR int digits10 = 33;
BOOST_STATIC_CONSTEXPR int max_digits10 = 36;
BOOST_STATIC_CONSTEXPR bool is_signed = true;
BOOST_STATIC_CONSTEXPR bool is_integer = false;
BOOST_STATIC_CONSTEXPR bool is_exact = false;
BOOST_STATIC_CONSTEXPR int radix = 2;
static boost::math::cstdfloat::detail::float_internal128_t epsilon () { return BOOST_CSTDFLOAT_FLOAT128_EPS; }
static boost::math::cstdfloat::detail::float_internal128_t round_error() { return BOOST_FLOAT128_C(0.5); }
BOOST_STATIC_CONSTEXPR int min_exponent = -16381;
BOOST_STATIC_CONSTEXPR int min_exponent10 = static_cast<int>((min_exponent * 301L) / 1000L);
BOOST_STATIC_CONSTEXPR int max_exponent = +16384;
BOOST_STATIC_CONSTEXPR int max_exponent10 = static_cast<int>((max_exponent * 301L) / 1000L);
BOOST_STATIC_CONSTEXPR bool has_infinity = true;
BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
static boost::math::cstdfloat::detail::float_internal128_t infinity () { return BOOST_FLOAT128_C(1.0) / BOOST_FLOAT128_C(0.0); }
static boost::math::cstdfloat::detail::float_internal128_t quiet_NaN () { return ::BOOST_CSTDFLOAT_FLOAT128_SQRT(BOOST_FLOAT128_C(-1.0)); }
static boost::math::cstdfloat::detail::float_internal128_t signaling_NaN() { return BOOST_FLOAT128_C(0.0); }
static boost::math::cstdfloat::detail::float_internal128_t denorm_min () { return BOOST_FLOAT128_C(0.0); }
BOOST_STATIC_CONSTEXPR bool is_iec559 = true;
BOOST_STATIC_CONSTEXPR bool is_bounded = false;
BOOST_STATIC_CONSTEXPR bool is_modulo = false;
BOOST_STATIC_CONSTEXPR bool traps = false;
BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest;
};
} // namespace std
#endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
#endif // _BOOST_CSTDFLOAT_LIMITS_2014_01_09_HPP_

View File

@@ -0,0 +1,440 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2014.
// Copyright John Maddock 2014.
// Copyright Paul Bristow 2014.
// 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)
//
// Implement the types for floating-point typedefs having specified widths.
#ifndef _BOOST_CSTDFLOAT_TYPES_2014_01_09_HPP_
#define _BOOST_CSTDFLOAT_TYPES_2014_01_09_HPP_
#include <float.h>
#include <limits>
#include <boost/static_assert.hpp>
#include <boost/math/tools/config.hpp>
// This is the beginning of the preamble.
// In this preamble, the preprocessor is used to query certain
// preprocessor definitions from <float.h>. Based on the results
// of these queries, an attempt is made to automatically detect
// the presence of built-in floating-point types having specified
// widths. These are *thought* to be conformant with IEEE-754,
// whereby an unequivocal test based on std::numeric_limits<>
// follows below.
// In addition, various macros that are used for initializing
// floating-point literal values having specified widths and
// some basic min/max values are defined.
// First, we will pre-load certain preprocessor definitions
// with a dummy value.
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 0
#define BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE 0
#define BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE 0
#define BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE 0
#define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 0
#define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 0
// Ensure that the compiler has a radix-2 floating-point representation.
#if (!defined(FLT_RADIX) || ((defined(FLT_RADIX) && (FLT_RADIX != 2))))
#error The compiler does not support any radix-2 floating-point types required for <boost/cstdfloat.hpp>.
#endif
// Check if built-in float is equivalent to float16_t, float32_t, float64_t, float80_t, or float128_t.
#if(defined(FLT_MANT_DIG) && defined(FLT_MAX_EXP))
#if ((FLT_MANT_DIG == 11) && (FLT_MAX_EXP == 16) && (BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT16_NATIVE_TYPE float
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 16
#undef BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE 1
#define BOOST_FLOAT16_C(x) (x ## F)
#define BOOST_CSTDFLOAT_FLOAT_16_MIN FLT_MIN
#define BOOST_CSTDFLOAT_FLOAT_16_MAX FLT_MAX
#elif((FLT_MANT_DIG == 24) && (FLT_MAX_EXP == 128) && (BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT32_NATIVE_TYPE float
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 32
#undef BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE 1
#define BOOST_FLOAT32_C(x) (x ## F)
#define BOOST_CSTDFLOAT_FLOAT_32_MIN FLT_MIN
#define BOOST_CSTDFLOAT_FLOAT_32_MAX FLT_MAX
#elif((FLT_MANT_DIG == 53) && (FLT_MAX_EXP == 1024) && (BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT64_NATIVE_TYPE float
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 64
#undef BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE 1
#define BOOST_FLOAT64_C(x) (x ## F)
#define BOOST_CSTDFLOAT_FLOAT_64_MIN FLT_MIN
#define BOOST_CSTDFLOAT_FLOAT_64_MAX FLT_MAX
#elif((FLT_MANT_DIG == 64) && (FLT_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE float
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 80
#undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 1
#define BOOST_FLOAT80_C(x) (x ## F)
#define BOOST_CSTDFLOAT_FLOAT_80_MIN FLT_MIN
#define BOOST_CSTDFLOAT_FLOAT_80_MAX FLT_MAX
#elif((FLT_MANT_DIG == 113) && (FLT_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE float
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128
#undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 1
#define BOOST_FLOAT128_C(x) (x ## F)
#define BOOST_CSTDFLOAT_FLOAT_128_MIN FLT_MIN
#define BOOST_CSTDFLOAT_FLOAT_128_MAX FLT_MAX
#endif
#endif
// Check if built-in double is equivalent to float16_t, float32_t, float64_t, float80_t, or float128_t.
#if(defined(DBL_MANT_DIG) && defined(DBL_MAX_EXP))
#if ((DBL_MANT_DIG == 11) && (DBL_MAX_EXP == 16) && (BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT16_NATIVE_TYPE double
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 16
#undef BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE 1
#define BOOST_FLOAT16_C(x) (x)
#define BOOST_CSTDFLOAT_FLOAT_16_MIN DBL_MIN
#define BOOST_CSTDFLOAT_FLOAT_16_MAX DBL_MAX
#elif((DBL_MANT_DIG == 24) && (DBL_MAX_EXP == 128) && (BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT32_NATIVE_TYPE double
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 32
#undef BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE 1
#define BOOST_FLOAT32_C(x) (x)
#define BOOST_CSTDFLOAT_FLOAT_32_MIN DBL_MIN
#define BOOST_CSTDFLOAT_FLOAT_32_MAX DBL_MAX
#elif((DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024) && (BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT64_NATIVE_TYPE double
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 64
#undef BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE 1
#define BOOST_FLOAT64_C(x) (x)
#define BOOST_CSTDFLOAT_FLOAT_64_MIN DBL_MIN
#define BOOST_CSTDFLOAT_FLOAT_64_MAX DBL_MAX
#elif((DBL_MANT_DIG == 64) && (DBL_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE double
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 80
#undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 1
#define BOOST_FLOAT80_C(x) (x)
#define BOOST_CSTDFLOAT_FLOAT_80_MIN DBL_MIN
#define BOOST_CSTDFLOAT_FLOAT_80_MAX DBL_MAX
#elif((DBL_MANT_DIG == 113) && (DBL_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE double
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128
#undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 1
#define BOOST_FLOAT128_C(x) (x)
#define BOOST_CSTDFLOAT_FLOAT_128_MIN DBL_MIN
#define BOOST_CSTDFLOAT_FLOAT_128_MAX DBL_MAX
#endif
#endif
// Disable check long double capability even if supported by compiler since some math runtime
// implementations are broken for long double.
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
// Check if built-in long double is equivalent to float16_t, float32_t, float64_t, float80_t, or float128_t.
#if(defined(LDBL_MANT_DIG) && defined(LDBL_MAX_EXP))
#if ((LDBL_MANT_DIG == 11) && (LDBL_MAX_EXP == 16) && (BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT16_NATIVE_TYPE long double
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 16
#undef BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE 1
#define BOOST_FLOAT16_C(x) (x ## L)
#define BOOST_CSTDFLOAT_FLOAT_16_MIN LDBL_MIN
#define BOOST_CSTDFLOAT_FLOAT_16_MAX LDBL_MAX
#elif((LDBL_MANT_DIG == 24) && (LDBL_MAX_EXP == 128) && (BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT32_NATIVE_TYPE long double
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 32
#undef BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE 1
#define BOOST_FLOAT32_C(x) (x ## L)
#define BOOST_CSTDFLOAT_FLOAT_32_MIN LDBL_MIN
#define BOOST_CSTDFLOAT_FLOAT_32_MAX LDBL_MAX
#elif((LDBL_MANT_DIG == 53) && (LDBL_MAX_EXP == 1024) && (BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT64_NATIVE_TYPE long double
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 64
#undef BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE 1
#define BOOST_FLOAT64_C(x) (x ## L)
#define BOOST_CSTDFLOAT_FLOAT_64_MIN LDBL_MIN
#define BOOST_CSTDFLOAT_FLOAT_64_MAX LDBL_MAX
#elif((LDBL_MANT_DIG == 64) && (LDBL_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE long double
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 80
#undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 1
#define BOOST_FLOAT80_C(x) (x ## L)
#define BOOST_CSTDFLOAT_FLOAT_80_MIN LDBL_MIN
#define BOOST_CSTDFLOAT_FLOAT_80_MAX LDBL_MAX
#elif((LDBL_MANT_DIG == 113) && (LDBL_MAX_EXP == 16384) && (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0))
#define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE long double
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128
#undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 1
#define BOOST_FLOAT128_C(x) (x ## L)
#define BOOST_CSTDFLOAT_FLOAT_128_MIN LDBL_MIN
#define BOOST_CSTDFLOAT_FLOAT_128_MAX LDBL_MAX
#endif
#endif
#endif
// Check if quadruple-precision is supported. Here, we are checking
// for the presence of __float128 from GCC's quadmath.h or _Quad
// from ICC's /Qlong-double flag). To query these, we use the
// BOOST_MATH_USE_FLOAT128 pre-processor definition from
// <boost/math/tools/config.hpp>.
#if (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
// Specify the underlying name of the internal 128-bit floating-point type definition.
namespace boost { namespace math { namespace cstdfloat { namespace detail {
#if defined(__GNUC__)
typedef __float128 float_internal128_t;
#elif defined(BOOST_INTEL)
typedef _Quad float_internal128_t;
#else
#error "Sorry, the compiler is neither GCC, nor Intel, I don't know how to configure <boost/cstdfloat.hpp>."
#endif
} } } } // boost::math::cstdfloat::detail
#define BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE boost::math::cstdfloat::detail::float_internal128_t
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 128
#undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 1
#define BOOST_FLOAT128_C(x) (x ## Q)
#define BOOST_CSTDFLOAT_FLOAT128_MIN 3.36210314311209350626267781732175260e-4932Q
#define BOOST_CSTDFLOAT_FLOAT128_MAX 1.18973149535723176508575932662800702e+4932Q
#define BOOST_CSTDFLOAT_FLOAT128_EPS 1.92592994438723585305597794258492732e-0034Q
#endif // Not BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT (i.e., the user would like to have libquadmath support)
// This is the end of the preamble, and also the end of the
// sections providing support for the C++ standard library
// for quadruple-precision.
// Now we use the results of the queries that have been obtained
// in the preamble (far above) for the final type definitions in
// the namespace boost.
// Make sure that the compiler has any floating-point type(s) whatsoever.
#if ( (BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 0) \
&& (BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 0) \
&& (BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 0) \
&& (BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 0) \
&& (BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 0))
#error The compiler does not support any of the floating-point types required for <boost/cstdfloat.hpp>.
#endif
// The following section contains the various min/max macros
// for the *leastN and *fastN types.
#if(BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 1)
#define BOOST_FLOAT_FAST16_MIN BOOST_CSTDFLOAT_FLOAT_16_MIN
#define BOOST_FLOAT_LEAST16_MIN BOOST_CSTDFLOAT_FLOAT_16_MIN
#define BOOST_FLOAT_FAST16_MAX BOOST_CSTDFLOAT_FLOAT_16_MAX
#define BOOST_FLOAT_LEAST16_MAX BOOST_CSTDFLOAT_FLOAT_16_MAX
#endif
#if(BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 1)
#define BOOST_FLOAT_FAST32_MIN BOOST_CSTDFLOAT_FLOAT_32_MIN
#define BOOST_FLOAT_LEAST32_MIN BOOST_CSTDFLOAT_FLOAT_32_MIN
#define BOOST_FLOAT_FAST32_MAX BOOST_CSTDFLOAT_FLOAT_32_MAX
#define BOOST_FLOAT_LEAST32_MAX BOOST_CSTDFLOAT_FLOAT_32_MAX
#endif
#if(BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 1)
#define BOOST_FLOAT_FAST64_MIN BOOST_CSTDFLOAT_FLOAT_64_MIN
#define BOOST_FLOAT_LEAST64_MIN BOOST_CSTDFLOAT_FLOAT_64_MIN
#define BOOST_FLOAT_FAST64_MAX BOOST_CSTDFLOAT_FLOAT_64_MAX
#define BOOST_FLOAT_LEAST64_MAX BOOST_CSTDFLOAT_FLOAT_64_MAX
#endif
#if(BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 1)
#define BOOST_FLOAT_FAST80_MIN BOOST_CSTDFLOAT_FLOAT_80_MIN
#define BOOST_FLOAT_LEAST80_MIN BOOST_CSTDFLOAT_FLOAT_80_MIN
#define BOOST_FLOAT_FAST80_MAX BOOST_CSTDFLOAT_FLOAT_80_MAX
#define BOOST_FLOAT_LEAST80_MAX BOOST_CSTDFLOAT_FLOAT_80_MAX
#endif
#if(BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 1)
#define BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T
#define BOOST_FLOAT_FAST128_MIN BOOST_CSTDFLOAT_FLOAT_128_MIN
#define BOOST_FLOAT_LEAST128_MIN BOOST_CSTDFLOAT_FLOAT_128_MIN
#define BOOST_FLOAT_FAST128_MAX BOOST_CSTDFLOAT_FLOAT_128_MAX
#define BOOST_FLOAT_LEAST128_MAX BOOST_CSTDFLOAT_FLOAT_128_MAX
#endif
// The following section contains the various min/max macros
// for the *floatmax types.
#if (BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 16)
#define BOOST_FLOATMAX_C(x) BOOST_FLOAT16_C(x)
#define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_16_MIN
#define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_16_MAX
#elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 32)
#define BOOST_FLOATMAX_C(x) BOOST_FLOAT32_C(x)
#define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_32_MIN
#define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_32_MAX
#elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 64)
#define BOOST_FLOATMAX_C(x) BOOST_FLOAT64_C(x)
#define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_64_MIN
#define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_64_MAX
#elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 80)
#define BOOST_FLOATMAX_C(x) BOOST_FLOAT80_C(x)
#define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_80_MIN
#define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_80_MAX
#elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 128)
#define BOOST_FLOATMAX_C(x) BOOST_FLOAT128_C(x)
#define BOOST_FLOATMAX_MIN BOOST_CSTDFLOAT_FLOAT_128_MIN
#define BOOST_FLOATMAX_MAX BOOST_CSTDFLOAT_FLOAT_128_MAX
#else
#error The maximum available floating-point width for <boost/cstdfloat.hpp> is undefined.
#endif
// And finally..., we define the floating-point typedefs having
// specified widths. The types are defined in the namespace boost.
// For simplicity, the least and fast types are type defined identically
// as the corresponding fixed-width type. This behavior may, however,
// be modified when being optimized for a given compiler implementation.
// In addition, a clear assessment of IEEE-754 comformance is carried out
// using compile-time assertion.
namespace boost
{
#if(BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE == 1)
typedef BOOST_CSTDFLOAT_FLOAT16_NATIVE_TYPE float16_t;
typedef boost::float16_t float_fast16_t;
typedef boost::float16_t float_least16_t;
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float16_t>::is_iec559 == true, "boost::float16_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float16_t>::radix == 2, "boost::float16_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float16_t>::digits == 11, "boost::float16_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float16_t>::max_exponent == 16, "boost::float16_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
#undef BOOST_CSTDFLOAT_FLOAT_16_MIN
#undef BOOST_CSTDFLOAT_FLOAT_16_MAX
#endif
#if(BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE == 1)
typedef BOOST_CSTDFLOAT_FLOAT32_NATIVE_TYPE float32_t;
typedef boost::float32_t float_fast32_t;
typedef boost::float32_t float_least32_t;
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float32_t>::is_iec559 == true, "boost::float32_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float32_t>::radix == 2, "boost::float32_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float32_t>::digits == 24, "boost::float32_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float32_t>::max_exponent == 128, "boost::float32_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
#undef BOOST_CSTDFLOAT_FLOAT_32_MIN
#undef BOOST_CSTDFLOAT_FLOAT_32_MAX
#endif
#if (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) && defined(__SUNPRO_CC)
#undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE 0
#undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE
#define BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE 0
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
#define BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH 64
#endif
#if(BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE == 1)
typedef BOOST_CSTDFLOAT_FLOAT64_NATIVE_TYPE float64_t;
typedef boost::float64_t float_fast64_t;
typedef boost::float64_t float_least64_t;
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float64_t>::is_iec559 == true, "boost::float64_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float64_t>::radix == 2, "boost::float64_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float64_t>::digits == 53, "boost::float64_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float64_t>::max_exponent == 1024, "boost::float64_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
#undef BOOST_CSTDFLOAT_FLOAT_64_MIN
#undef BOOST_CSTDFLOAT_FLOAT_64_MAX
#endif
#if(BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE == 1)
typedef BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE float80_t;
typedef boost::float80_t float_fast80_t;
typedef boost::float80_t float_least80_t;
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float80_t>::is_iec559 == true, "boost::float80_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float80_t>::radix == 2, "boost::float80_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float80_t>::digits == 64, "boost::float80_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float80_t>::max_exponent == 16384, "boost::float80_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
#undef BOOST_CSTDFLOAT_FLOAT_80_MIN
#undef BOOST_CSTDFLOAT_FLOAT_80_MAX
#endif
#if(BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE == 1)
typedef BOOST_CSTDFLOAT_FLOAT128_NATIVE_TYPE float128_t;
typedef boost::float128_t float_fast128_t;
typedef boost::float128_t float_least128_t;
#if defined(BOOST_CSTDFLOAT_HAS_INTERNAL_FLOAT128_T) && defined(BOOST_MATH_USE_FLOAT128) && !defined(BOOST_CSTDFLOAT_NO_LIBQUADMATH_SUPPORT)
// This configuration does not *yet* support std::numeric_limits<boost::float128_t>.
// Support for std::numeric_limits<boost::float128_t> is added in the detail
// file <boost/math/cstdfloat/cstdfloat_limits.hpp>.
#else
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float128_t>::is_iec559 == true, "boost::float128_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float128_t>::radix == 2, "boost::float128_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float128_t>::digits == 113, "boost::float128_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
BOOST_STATIC_ASSERT_MSG(std::numeric_limits<boost::float128_t>::max_exponent == 16384, "boost::float128_t has been detected in <boost/cstdfloat>, but verification with std::numeric_limits fails");
#endif
#undef BOOST_CSTDFLOAT_FLOAT_128_MIN
#undef BOOST_CSTDFLOAT_FLOAT_128_MAX
#endif
#if (BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 16)
typedef boost::float16_t floatmax_t;
#elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 32)
typedef boost::float32_t floatmax_t;
#elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 64)
typedef boost::float64_t floatmax_t;
#elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 80)
typedef boost::float80_t floatmax_t;
#elif(BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH == 128)
typedef boost::float128_t floatmax_t;
#else
#error The maximum available floating-point width for <boost/cstdfloat.hpp> is undefined.
#endif
#undef BOOST_CSTDFLOAT_HAS_FLOAT16_NATIVE_TYPE
#undef BOOST_CSTDFLOAT_HAS_FLOAT32_NATIVE_TYPE
#undef BOOST_CSTDFLOAT_HAS_FLOAT64_NATIVE_TYPE
#undef BOOST_CSTDFLOAT_HAS_FLOAT80_NATIVE_TYPE
#undef BOOST_CSTDFLOAT_HAS_FLOAT128_NATIVE_TYPE
#undef BOOST_CSTDFLOAT_MAXIMUM_AVAILABLE_WIDTH
}
// namespace boost
#endif // _BOOST_CSTDFLOAT_BASE_TYPES_2014_01_09_HPP_

View File

@@ -0,0 +1,53 @@
// Copyright John Maddock 2006, 2007.
// Copyright Paul A. Bristow 2006, 2007, 2009, 2010.
// 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 convenient if many are used
// - to avoid including each distribution individually.
#ifndef BOOST_MATH_DISTRIBUTIONS_HPP
#define BOOST_MATH_DISTRIBUTIONS_HPP
#include <boost/math/distributions/arcsine.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/geometric.hpp>
#include <boost/math/distributions/hyperexponential.hpp>
#include <boost/math/distributions/hypergeometric.hpp>
#include <boost/math/distributions/inverse_chi_squared.hpp>
#include <boost/math/distributions/inverse_gamma.hpp>
#include <boost/math/distributions/inverse_gaussian.hpp>
#include <boost/math/distributions/laplace.hpp>
#include <boost/math/distributions/logistic.hpp>
#include <boost/math/distributions/lognormal.hpp>
#include <boost/math/distributions/negative_binomial.hpp>
#include <boost/math/distributions/non_central_chi_squared.hpp>
#include <boost/math/distributions/non_central_beta.hpp>
#include <boost/math/distributions/non_central_f.hpp>
#include <boost/math/distributions/non_central_t.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/skew_normal.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>
#include <boost/math/distributions/find_scale.hpp>
#include <boost/math/distributions/find_location.hpp>
#endif // BOOST_MATH_DISTRIBUTIONS_HPP

View File

@@ -0,0 +1,535 @@
// boost/math/distributions/arcsine.hpp
// Copyright John Maddock 2014.
// Copyright Paul A. Bristow 2014.
// 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/arcsine_distribution
// The arcsine Distribution is a continuous probability distribution.
// http://en.wikipedia.org/wiki/Arcsine_distribution
// http://www.wolframalpha.com/input/?i=ArcSinDistribution
// Standard arcsine distribution is a special case of beta distribution with both a & b = one half,
// and 0 <= x <= 1.
// It is generalized to include any bounded support a <= x <= b from 0 <= x <= 1
// by Wolfram and Wikipedia,
// but using location and scale parameters by
// Virtual Laboratories in Probability and Statistics http://www.math.uah.edu/stat/index.html
// http://www.math.uah.edu/stat/special/Arcsine.html
// The end-point version is simpler and more obvious, so we implement that.
// TODO Perhaps provide location and scale functions?
#ifndef BOOST_MATH_DIST_ARCSINE_HPP
#define BOOST_MATH_DIST_ARCSINE_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/distributions/complement.hpp> // complements.
#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks.
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/fpclassify.hpp> // isnan.
#if defined (BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4702) // Unreachable code,
// in domain_error_imp in error_handling.
#endif
#include <utility>
#include <exception> // For std::domain_error.
namespace boost
{
namespace math
{
namespace arcsine_detail
{
// Common error checking routines for arcsine distribution functions:
// Duplicating for x_min and x_max provides specific error messages.
template <class RealType, class Policy>
inline bool check_x_min(const char* function, const RealType& x, RealType* result, const Policy& pol)
{
if (!(boost::math::isfinite)(x))
{
*result = policies::raise_domain_error<RealType>(
function,
"x_min argument is %1%, but must be finite !", x, pol);
return false;
}
return true;
} // bool check_x_min
template <class RealType, class Policy>
inline bool check_x_max(const char* function, const RealType& x, RealType* result, const Policy& pol)
{
if (!(boost::math::isfinite)(x))
{
*result = policies::raise_domain_error<RealType>(
function,
"x_max argument is %1%, but must be finite !", x, pol);
return false;
}
return true;
} // bool check_x_max
template <class RealType, class Policy>
inline bool check_x_minmax(const char* function, const RealType& x_min, const RealType& x_max, RealType* result, const Policy& pol)
{ // Check x_min < x_max
if (x_min >= x_max)
{
std::string msg = "x_max argument is %1%, but must be > x_min = " + lexical_cast<std::string>(x_min) + "!";
*result = policies::raise_domain_error<RealType>(
function,
msg.c_str(), x_max, pol);
// "x_max argument is %1%, but must be > x_min !", x_max, pol);
// "x_max argument is %1%, but must be > x_min %2!", x_max, x_min, pol); would be better.
// But would require replication of all helpers functions in /policies/error_handling.hpp for two values,
// as well as two value versions of raise_error, raise_domain_error and do_format ...
// so use slightly hacky lexical_cast to string instead.
return false;
}
return true;
} // bool check_x_minmax
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_min, const RealType& x_max, const RealType& x, RealType* result, const Policy& pol)
{ // Check x finite and x_min < x < x_max.
if (!(boost::math::isfinite)(x))
{
*result = policies::raise_domain_error<RealType>(
function,
"x argument is %1%, but must be finite !", x, pol);
return false;
}
if ((x < x_min) || (x > x_max))
{
// std::cout << x_min << ' ' << x << x_max << std::endl;
*result = policies::raise_domain_error<RealType>(
function,
"x argument is %1%, but must be x_min < x < x_max !", x, pol);
// For example:
// Error in function boost::math::pdf(arcsine_distribution<double> const&, double) : x argument is -1.01, but must be x_min < x < x_max !
// TODO Perhaps show values of x_min and x_max?
return false;
}
return true;
} // bool check_x
template <class RealType, class Policy>
inline bool check_dist(const char* function, const RealType& x_min, const RealType& x_max, RealType* result, const Policy& pol)
{ // Check both x_min and x_max finite, and x_min < x_max.
return check_x_min(function, x_min, result, pol)
&& check_x_max(function, x_max, result, pol)
&& check_x_minmax(function, x_min, x_max, result, pol);
} // bool check_dist
template <class RealType, class Policy>
inline bool check_dist_and_x(const char* function, const RealType& x_min, const RealType& x_max, RealType x, RealType* result, const Policy& pol)
{
return check_dist(function, x_min, x_max, result, pol)
&& arcsine_detail::check_x(function, x_min, x_max, x, result, pol);
} // bool check_dist_and_x
template <class RealType, class Policy>
inline bool check_dist_and_prob(const char* function, const RealType& x_min, const RealType& x_max, RealType p, RealType* result, const Policy& pol)
{
return check_dist(function, x_min, x_max, result, pol)
&& check_prob(function, p, result, pol);
} // bool check_dist_and_prob
} // namespace arcsine_detail
template <class RealType = double, class Policy = policies::policy<> >
class arcsine_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
arcsine_distribution(RealType x_min = 0, RealType x_max = 1) : m_x_min(x_min), m_x_max(x_max)
{ // Default beta (alpha = beta = 0.5) is standard arcsine with x_min = 0, x_max = 1.
// Generalized to allow x_min and x_max to be specified.
RealType result;
arcsine_detail::check_dist(
"boost::math::arcsine_distribution<%1%>::arcsine_distribution",
m_x_min,
m_x_max,
&result, Policy());
} // arcsine_distribution constructor.
// Accessor functions:
RealType x_min() const
{
return m_x_min;
}
RealType x_max() const
{
return m_x_max;
}
private:
RealType m_x_min; // Two x min and x max parameters of the arcsine distribution.
RealType m_x_max;
}; // template <class RealType, class Policy> class arcsine_distribution
// Convenient typedef to construct double version.
typedef arcsine_distribution<double> arcsine;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const arcsine_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>(dist.x_min()), static_cast<RealType>(dist.x_max()));
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const arcsine_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>(static_cast<RealType>(dist.x_min()), static_cast<RealType>(dist.x_max()));
}
template <class RealType, class Policy>
inline RealType mean(const arcsine_distribution<RealType, Policy>& dist)
{ // Mean of arcsine distribution .
RealType result;
RealType x_min = dist.x_min();
RealType x_max = dist.x_max();
if (false == arcsine_detail::check_dist(
"boost::math::mean(arcsine_distribution<%1%> const&, %1% )",
x_min,
x_max,
&result, Policy())
)
{
return result;
}
return (x_min + x_max) / 2;
} // mean
template <class RealType, class Policy>
inline RealType variance(const arcsine_distribution<RealType, Policy>& dist)
{ // Variance of standard arcsine distribution = (1-0)/8 = 0.125.
RealType result;
RealType x_min = dist.x_min();
RealType x_max = dist.x_max();
if (false == arcsine_detail::check_dist(
"boost::math::variance(arcsine_distribution<%1%> const&, %1% )",
x_min,
x_max,
&result, Policy())
)
{
return result;
}
return (x_max - x_min) * (x_max - x_min) / 8;
} // variance
template <class RealType, class Policy>
inline RealType mode(const arcsine_distribution<RealType, Policy>& /* dist */)
{ //There are always [*two] values for the mode, at ['x_min] and at ['x_max], default 0 and 1,
// so instead we raise the exception domain_error.
return policies::raise_domain_error<RealType>(
"boost::math::mode(arcsine_distribution<%1%>&)",
"The arcsine distribution has two modes at x_min and x_max: "
"so the return value is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy());
} // mode
template <class RealType, class Policy>
inline RealType median(const arcsine_distribution<RealType, Policy>& dist)
{ // Median of arcsine distribution (a + b) / 2 == mean.
RealType x_min = dist.x_min();
RealType x_max = dist.x_max();
RealType result;
if (false == arcsine_detail::check_dist(
"boost::math::median(arcsine_distribution<%1%> const&, %1% )",
x_min,
x_max,
&result, Policy())
)
{
return result;
}
return (x_min + x_max) / 2;
}
template <class RealType, class Policy>
inline RealType skewness(const arcsine_distribution<RealType, Policy>& dist)
{
RealType result;
RealType x_min = dist.x_min();
RealType x_max = dist.x_max();
if (false == arcsine_detail::check_dist(
"boost::math::skewness(arcsine_distribution<%1%> const&, %1% )",
x_min,
x_max,
&result, Policy())
)
{
return result;
}
return 0;
} // skewness
template <class RealType, class Policy>
inline RealType kurtosis_excess(const arcsine_distribution<RealType, Policy>& dist)
{
RealType result;
RealType x_min = dist.x_min();
RealType x_max = dist.x_max();
if (false == arcsine_detail::check_dist(
"boost::math::kurtosis_excess(arcsine_distribution<%1%> const&, %1% )",
x_min,
x_max,
&result, Policy())
)
{
return result;
}
result = -3;
return result / 2;
} // kurtosis_excess
template <class RealType, class Policy>
inline RealType kurtosis(const arcsine_distribution<RealType, Policy>& dist)
{
RealType result;
RealType x_min = dist.x_min();
RealType x_max = dist.x_max();
if (false == arcsine_detail::check_dist(
"boost::math::kurtosis(arcsine_distribution<%1%> const&, %1% )",
x_min,
x_max,
&result, Policy())
)
{
return result;
}
return 3 + kurtosis_excess(dist);
} // kurtosis
template <class RealType, class Policy>
inline RealType pdf(const arcsine_distribution<RealType, Policy>& dist, const RealType& xx)
{ // Probability Density/Mass Function arcsine.
BOOST_FPU_EXCEPTION_GUARD
BOOST_MATH_STD_USING // For ADL of std functions.
static const char* function = "boost::math::pdf(arcsine_distribution<%1%> const&, %1%)";
RealType lo = dist.x_min();
RealType hi = dist.x_max();
RealType x = xx;
// Argument checks:
RealType result = 0;
if (false == arcsine_detail::check_dist_and_x(
function,
lo, hi, x,
&result, Policy()))
{
return result;
}
using boost::math::constants::pi;
result = static_cast<RealType>(1) / (pi<RealType>() * sqrt((x - lo) * (hi - x)));
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const arcsine_distribution<RealType, Policy>& dist, const RealType& x)
{ // Cumulative Distribution Function arcsine.
BOOST_MATH_STD_USING // For ADL of std functions.
static const char* function = "boost::math::cdf(arcsine_distribution<%1%> const&, %1%)";
RealType x_min = dist.x_min();
RealType x_max = dist.x_max();
// Argument checks:
RealType result = 0;
if (false == arcsine_detail::check_dist_and_x(
function,
x_min, x_max, x,
&result, Policy()))
{
return result;
}
// Special cases:
if (x == x_min)
{
return 0;
}
else if (x == x_max)
{
return 1;
}
using boost::math::constants::pi;
result = static_cast<RealType>(2) * asin(sqrt((x - x_min) / (x_max - x_min))) / pi<RealType>();
return result;
} // arcsine cdf
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<arcsine_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function arcsine.
BOOST_MATH_STD_USING // For ADL of std functions.
static const char* function = "boost::math::cdf(arcsine_distribution<%1%> const&, %1%)";
RealType x = c.param;
arcsine_distribution<RealType, Policy> const& dist = c.dist;
RealType x_min = dist.x_min();
RealType x_max = dist.x_max();
// Argument checks:
RealType result = 0;
if (false == arcsine_detail::check_dist_and_x(
function,
x_min, x_max, x,
&result, Policy()))
{
return result;
}
if (x == x_min)
{
return 0;
}
else if (x == x_max)
{
return 1;
}
using boost::math::constants::pi;
// Naive version x = 1 - x;
// result = static_cast<RealType>(2) * asin(sqrt((x - x_min) / (x_max - x_min))) / pi<RealType>();
// is less accurate, so use acos instead of asin for complement.
result = static_cast<RealType>(2) * acos(sqrt((x - x_min) / (x_max - x_min))) / pi<RealType>();
return result;
} // arcine ccdf
template <class RealType, class Policy>
inline RealType quantile(const arcsine_distribution<RealType, Policy>& dist, const RealType& p)
{
// Quantile or Percent Point arcsine 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.
BOOST_MATH_STD_USING // For ADL of std functions.
using boost::math::constants::half_pi;
static const char* function = "boost::math::quantile(arcsine_distribution<%1%> const&, %1%)";
RealType result = 0; // of argument checks:
RealType x_min = dist.x_min();
RealType x_max = dist.x_max();
if (false == arcsine_detail::check_dist_and_prob(
function,
x_min, x_max, p,
&result, Policy()))
{
return result;
}
// Special cases:
if (p == 0)
{
return 0;
}
if (p == 1)
{
return 1;
}
RealType sin2hpip = sin(half_pi<RealType>() * p);
RealType sin2hpip2 = sin2hpip * sin2hpip;
result = -x_min * sin2hpip2 + x_min + x_max * sin2hpip2;
return result;
} // quantile
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<arcsine_distribution<RealType, Policy>, RealType>& c)
{
// Complement Quantile or Percent Point arcsine function.
// Return the number of expected x for a given
// complement of the probability q.
BOOST_MATH_STD_USING // For ADL of std functions.
using boost::math::constants::half_pi;
static const char* function = "boost::math::quantile(arcsine_distribution<%1%> const&, %1%)";
// Error checks:
RealType q = c.param;
const arcsine_distribution<RealType, Policy>& dist = c.dist;
RealType result = 0;
RealType x_min = dist.x_min();
RealType x_max = dist.x_max();
if (false == arcsine_detail::check_dist_and_prob(
function,
x_min,
x_max,
q,
&result, Policy()))
{
return result;
}
// Special cases:
if (q == 1)
{
return 0;
}
if (q == 0)
{
return 1;
}
// Naive RealType p = 1 - q; result = sin(half_pi<RealType>() * p); loses accuracy, so use a cos alternative instead.
//result = cos(half_pi<RealType>() * q); // for arcsine(0,1)
//result = result * result;
// For generalized arcsine:
RealType cos2hpip = cos(half_pi<RealType>() * q);
RealType cos2hpip2 = cos2hpip * cos2hpip;
result = -x_min * cos2hpip2 + x_min + x_max * cos2hpip2;
return result;
} // 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_ARCSINE_HPP

View File

@@ -0,0 +1,336 @@
// 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 */, const mpl::true_&)
{
return check_success_fraction(function, p, result, Policy());
}
template <class RealType, class Policy>
inline bool check_dist(const char* , const RealType& , RealType* , const Policy& /* pol */, const mpl::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_dist(function, p, result, Policy(), typename policies::constructor_error_check<Policy>::type());
}
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(), typename policies::method_error_check<Policy>::type()) == 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(), typename policies::method_error_check<Policy>::type()) && 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>(static_cast<RealType>(0), static_cast<RealType>(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>(static_cast<RealType>(0), static_cast<RealType>(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 = 0; // 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 = 0;
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 = 0;
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 = 0; // 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 = 0;
if(false == bernoulli_detail::check_dist_and_prob(
"boost::math::quantile(bernoulli_distribution<%1%>, %1%)",
dist.success_fraction(),
q,
&result, Policy()))
{
return result;
}
if (q <= 1 - dist.success_fraction())
{ // // q <= cdf(complement(dist, 0)) == pdf(dist, 0)
return 1;
}
else
{
return 0;
}
} // quantile complemented.
template <class RealType, class Policy>
inline RealType mode(const bernoulli_distribution<RealType, Policy>& dist)
{
return static_cast<RealType>((dist.success_fraction() <= 0.5) ? 0 : 1); // p = 0.5 can be 0 or 1
}
template <class RealType, class Policy>
inline RealType skewness(const bernoulli_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING; // Aid ADL for sqrt.
RealType p = dist.success_fraction();
return (1 - 2 * p) / sqrt(p * (1 - p));
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const bernoulli_distribution<RealType, Policy>& dist)
{
RealType p = dist.success_fraction();
// Note Wolfram says this is kurtosis in text, but gamma2 is the kurtosis excess,
// and Wikipedia also says this is the kurtosis excess formula.
// return (6 * p * p - 6 * p + 1) / (p * (1 - p));
// But Wolfram kurtosis article gives this simpler formula for kurtosis excess:
return 1 / (1 - p) + 1/p -6;
}
template <class RealType, class Policy>
inline RealType kurtosis(const bernoulli_distribution<RealType, Policy>& dist)
{
RealType p = dist.success_fraction();
return 1 / (1 - p) + 1/p -6 + 3;
// Simpler than:
// return (6 * p * p - 6 * p + 1) / (p * (1 - p)) + 3;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_MATH_SPECIAL_BERNOULLI_HPP

View File

@@ -0,0 +1,541 @@
// 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)
&& beta_detail::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 l_alpha = 1, RealType l_beta = 1) : m_alpha(l_alpha), m_beta(l_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 = 0; // 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 = 0; // 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 = 0; // 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 = 0; // 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>(static_cast<RealType>(0), static_cast<RealType>(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>(static_cast<RealType>(0), static_cast<RealType>(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 = 0;
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 = 0;
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 = 0;
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 = 0; // 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 = 0;
RealType a = dist.alpha();
RealType b = dist.beta();
if(false == beta_detail::check_dist_and_prob(
function,
a,
b,
q,
&result, Policy()))
{
return result;
}
// Special cases:
if(q == 1)
{
return 0;
}
if(q == 0)
{
return 1;
}
return ibetac_inv(a, b, q, static_cast<RealType*>(0), Policy());
} // Quantile Complement
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#if defined (BOOST_MSVC)
# pragma warning(pop)
#endif
#endif // BOOST_MATH_DIST_BETA_HPP

View File

@@ -0,0 +1,728 @@
// 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, bool comp)
{ // 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 = 0;
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.
if(success_fraction == 1)
{ // our formulae break down in this case:
return p > 0.5f ? trials : 0;
}
// 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,
comp ? q : p,
comp,
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 = 0;
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 = 0;
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 = 0;
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 = 0;
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>(static_cast<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 = 0; // initialization silences some compiler warnings
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 = 0;
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 = 0;
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, RealType(1-p), false);
} // quantile
template <class RealType, class Policy>
RealType quantile(const complemented2_type<binomial_distribution<RealType, Policy>, RealType>& c)
{
return binomial_detail::quantile_imp(c.dist, RealType(1-c.param), c.param, true);
} // quantile
template <class RealType, class Policy>
inline RealType mode(const binomial_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // ADL of std functions.
RealType p = dist.success_fraction();
RealType n = dist.trials();
return floor(p * (n + 1));
}
template <class RealType, class Policy>
inline RealType median(const binomial_distribution<RealType, Policy>& dist)
{ // Bounds for the median of the negative binomial distribution
// VAN DE VEN R. ; WEBER N. C. ;
// Univ. Sydney, school mathematics statistics, Sydney N.S.W. 2006, AUSTRALIE
// Metrika (Metrika) ISSN 0026-1335 CODEN MTRKA8
// 1993, vol. 40, no3-4, pp. 185-189 (4 ref.)
// Bounds for median and 50 percetage point of binomial and negative binomial distribution
// Metrika, ISSN 0026-1335 (Print) 1435-926X (Online)
// Volume 41, Number 1 / December, 1994, DOI 10.1007/BF01895303
BOOST_MATH_STD_USING // ADL of std functions.
RealType p = dist.success_fraction();
RealType n = dist.trials();
// Wikipedia says one of floor(np) -1, floor (np), floor(np) +1
return floor(p * n); // Chose the middle value.
}
template <class RealType, class Policy>
inline RealType skewness(const binomial_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // ADL of std functions.
RealType p = dist.success_fraction();
RealType n = dist.trials();
return (1 - 2 * p) / sqrt(n * p * (1 - p));
}
template <class RealType, class Policy>
inline RealType kurtosis(const binomial_distribution<RealType, Policy>& dist)
{
RealType p = dist.success_fraction();
RealType n = dist.trials();
return 3 - 6 / n + 1 / (n * p * (1 - p));
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const binomial_distribution<RealType, Policy>& dist)
{
RealType p = dist.success_fraction();
RealType q = 1 - p;
RealType n = dist.trials();
return (1 - 6 * p * q) / (n * p * q);
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_MATH_SPECIAL_BINOMIAL_HPP

View File

@@ -0,0 +1,362 @@
// 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 <boost/config/no_tr1/cmath.hpp>
#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 = 0;
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 = 0;
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 ? RealType(location - result) : RealType(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 l_location = 0, RealType l_scale = 1)
: m_a(l_location), m_hg(l_scale)
{
static const char* function = "boost::math::cauchy_distribution<%1%>::cauchy_distribution";
RealType result;
detail::check_location(function, l_location, &result, Policy());
detail::check_scale(function, l_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.
if (std::numeric_limits<RealType>::has_infinity)
{
return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
}
else
{ // Can only use max_value.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max.
}
}
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.
if (std::numeric_limits<RealType>::has_infinity)
{
return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
}
else
{ // Can only use max_value.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-tools::max_value<RealType>(), max_value<RealType>()); // - to + max.
}
}
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 = 0;
RealType location = dist.location();
RealType scale = dist.scale();
if(false == detail::check_scale("boost::math::pdf(cauchy<%1%>&, %1%)", scale, &result, Policy()))
{
return result;
}
if(false == detail::check_location("boost::math::pdf(cauchy<%1%>&, %1%)", location, &result, Policy()))
{
return result;
}
if((boost::math::isinf)(x))
{
return 0; // pdf + and - infinity is zero.
}
// These produce MSVC 4127 warnings, so the above used instead.
//if(std::numeric_limits<RealType>::has_infinity && abs(x) == std::numeric_limits<RealType>::infinity())
//{ // pdf + and - infinity is zero.
// return 0;
//}
if(false == detail::check_x(function, x, &result, Policy()))
{ // Catches x = NaN
return result;
}
RealType xs = (x - location) / scale;
result = 1 / (constants::pi<RealType>() * scale * (1 + xs * xs));
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const cauchy_distribution<RealType, Policy>& dist, const RealType& x)
{
return detail::cdf_imp(dist, x, false);
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const cauchy_distribution<RealType, Policy>& dist, const RealType& p)
{
return detail::quantile_imp(dist, p, false);
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<cauchy_distribution<RealType, Policy>, RealType>& c)
{
return detail::cdf_imp(c.dist, c.param, true);
} // cdf complement
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<cauchy_distribution<RealType, Policy>, RealType>& c)
{
return detail::quantile_imp(c.dist, c.param, true);
} // quantile complement
template <class RealType, class Policy>
inline RealType mean(const cauchy_distribution<RealType, Policy>&)
{ // There is no mean:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
return policies::raise_domain_error<RealType>(
"boost::math::mean(cauchy<%1%>&)",
"The Cauchy distribution does not have a mean: "
"the only possible return value is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy());
}
template <class RealType, class Policy>
inline RealType variance(const cauchy_distribution<RealType, Policy>& /*dist*/)
{
// There is no variance:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
return policies::raise_domain_error<RealType>(
"boost::math::variance(cauchy<%1%>&)",
"The Cauchy distribution does not have a variance: "
"the only possible return value is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy());
}
template <class RealType, class Policy>
inline RealType mode(const cauchy_distribution<RealType, Policy>& dist)
{
return dist.location();
}
template <class RealType, class Policy>
inline RealType median(const cauchy_distribution<RealType, Policy>& dist)
{
return dist.location();
}
template <class RealType, class Policy>
inline RealType skewness(const cauchy_distribution<RealType, Policy>& /*dist*/)
{
// There is no skewness:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
return policies::raise_domain_error<RealType>(
"boost::math::skewness(cauchy<%1%>&)",
"The Cauchy distribution does not have a skewness: "
"the only possible return value is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy()); // infinity?
}
template <class RealType, class Policy>
inline RealType kurtosis(const cauchy_distribution<RealType, Policy>& /*dist*/)
{
// There is no kurtosis:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
return policies::raise_domain_error<RealType>(
"boost::math::kurtosis(cauchy<%1%>&)",
"The Cauchy distribution does not have a kurtosis: "
"the only possible return value is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy());
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const cauchy_distribution<RealType, Policy>& /*dist*/)
{
// There is no kurtosis excess:
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
return policies::raise_domain_error<RealType>(
"boost::math::kurtosis_excess(cauchy<%1%>&)",
"The Cauchy distribution does not have a kurtosis: "
"the only possible return value is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy());
}
} // namespace math
} // namespace boost
#ifdef _MSC_VER
#pragma warning(pop)
#endif
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_CAUCHY_HPP

View File

@@ -0,0 +1,364 @@
// Copyright John Maddock 2006, 2007.
// Copyright Paul A. Bristow 2008, 2010.
// 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 is a positive real number.
}; // class chi_squared_distribution
typedef chi_squared_distribution<double> chi_squared;
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127)
#endif
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.
if (std::numeric_limits<RealType>::has_infinity)
{
return std::pair<RealType, RealType>(static_cast<RealType>(0), std::numeric_limits<RealType>::infinity()); // 0 to + infinity.
}
else
{
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // 0 to + max.
}
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
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>(static_cast<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%>&)";
// Most sources only define mode for df >= 2,
// but for 0 <= df <= 2, the pdf maximum actually occurs at random variate = 0;
// So one could extend the definition of mode thus:
//if(df < 0)
//{
// return policies::raise_domain_error<RealType>(
// function,
// "Chi-Squared distribution only has a mode for degrees of freedom >= 0, but got degrees of freedom = %1%.",
// df, Policy());
//}
//return (df <= 2) ? 0 : df - 2;
if(df < 2)
return policies::raise_domain_error<RealType>(
function,
"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)
{ // Constructor
}
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
{ // ratio <= 0
RealType r = 1 + ratio;
result = cdf(complement(cs, quantile(cs, alpha) / r)) - beta;
}
return result;
}
private:
RealType alpha;
RealType beta;
RealType ratio; // Difference from variance / variance, so fractional.
};
} // 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()))
{ // Either probability is outside 0 to 1.
return error_result;
}
if(hint <= 0)
{ // No hint given, so guess df = 1.
hint = 1;
}
detail::df_estimator<RealType, Policy> f(alpha, beta, variance, difference_from_variance);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::pair<RealType, RealType> r =
tools::bracket_and_solve_root(f, hint, RealType(2), false, tol, max_iter, Policy());
RealType result = r.first + (r.second - r.first) / 2;
if(max_iter >= policies::get_max_root_iterations<Policy>())
{
policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
" either there is no answer to how many degrees of freedom are required"
" or the answer is infinite. Current best guess is %1%", result, Policy());
}
return result;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_MATH_DISTRIBUTIONS_CHI_SQUARED_HPP

View File

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

View File

@@ -0,0 +1,194 @@
// Copyright John Maddock 2006, 2007.
// Copyright Paul A. Bristow 2006, 2007, 2012.
// 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;
// using boost::math::isnan;
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)
{ // df > 0 but NOT +infinity allowed.
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_df_gt0_to_inf(const char* function, RealType const& df, RealType* result, const Policy& pol)
{ // df > 0 or +infinity are allowed.
if( (df <= 0) || (boost::math::isnan)(df) )
{ // is bad df <= 0 or NaN or -infinity.
*result = policies::raise_domain_error<RealType>(
function,
"Degrees of freedom argument is %1%, but must be > 0 !", df, pol);
return false;
}
return true;
} // check_df_gt0_to_inf
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)
{
// Note that this test catches both infinity and NaN.
// Some distributions permit x to be infinite, so these must be tested 1st and return,
// leaving this test to catch any NaNs.
// See Normal, Logistic, Laplace and Cauchy for example.
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;
} // bool check_x
template <class RealType, class Policy>
inline bool check_x_gt0(
const char* function,
RealType x,
RealType* result,
const Policy& pol)
{
if(x <= 0)
{
*result = policies::raise_domain_error<RealType>(
function,
"Random variate x is %1%, but must be > 0!", 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.
} // bool check_x_gt0
template <class RealType, class Policy>
inline bool check_positive_x(
const char* function,
RealType x,
RealType* result,
const Policy& pol)
{
if(!(boost::math::isfinite)(x) || (x < 0))
{
*result = policies::raise_domain_error<RealType>(
function,
"Random variate x is %1%, but must be finite and >= 0!", 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.
}
template <class RealType, class Policy>
inline bool check_non_centrality(
const char* function,
RealType ncp,
RealType* result,
const Policy& pol)
{
if((ncp < 0) || !(boost::math::isfinite)(ncp))
{ // Assume scale == 0 is NOT valid for any distribution.
*result = policies::raise_domain_error<RealType>(
function,
"Non centrality parameter is %1%, but must be > 0 !", ncp, pol);
return false;
}
return true;
}
template <class RealType, class Policy>
inline bool check_finite(
const char* function,
RealType x,
RealType* result,
const Policy& pol)
{
if(!(boost::math::isfinite)(x))
{ // Assume scale == 0 is NOT valid for any distribution.
*result = policies::raise_domain_error<RealType>(
function,
"Parameter is %1%, but must be finite !", x, pol);
return false;
}
return true;
}
} // namespace detail
} // namespace math
} // namespace boost
#endif // BOOST_MATH_DISTRIBUTIONS_COMMON_ERROR_HANDLING_HPP

View File

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

View File

@@ -0,0 +1,149 @@
// Copyright John Maddock 2008.
// 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_MODE_HPP
#define BOOST_MATH_DISTRIBUTIONS_DETAIL_MODE_HPP
#include <boost/math/tools/minima.hpp> // function minimization for mode
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/distributions/fwd.hpp>
namespace boost{ namespace math{ namespace detail{
template <class Dist>
struct pdf_minimizer
{
pdf_minimizer(const Dist& d)
: dist(d) {}
typename Dist::value_type operator()(const typename Dist::value_type& x)
{
return -pdf(dist, x);
}
private:
Dist dist;
};
template <class Dist>
typename Dist::value_type generic_find_mode(const Dist& dist, typename Dist::value_type guess, const char* function, typename Dist::value_type step = 0)
{
BOOST_MATH_STD_USING
typedef typename Dist::value_type value_type;
typedef typename Dist::policy_type policy_type;
//
// Need to begin by bracketing the maxima of the PDF:
//
value_type maxval;
value_type upper_bound = guess;
value_type lower_bound;
value_type v = pdf(dist, guess);
if(v == 0)
{
//
// Oops we don't know how to handle this, or even in which
// direction we should move in, treat as an evaluation error:
//
return policies::raise_evaluation_error(
function,
"Could not locate a starting location for the search for the mode, original guess was %1%", guess, policy_type());
}
do
{
maxval = v;
if(step != 0)
upper_bound += step;
else
upper_bound *= 2;
v = pdf(dist, upper_bound);
}while(maxval < v);
lower_bound = upper_bound;
do
{
maxval = v;
if(step != 0)
lower_bound -= step;
else
lower_bound /= 2;
v = pdf(dist, lower_bound);
}while(maxval < v);
boost::uintmax_t max_iter = policies::get_max_root_iterations<policy_type>();
value_type result = tools::brent_find_minima(
pdf_minimizer<Dist>(dist),
lower_bound,
upper_bound,
policies::digits<value_type, policy_type>(),
max_iter).first;
if(max_iter >= policies::get_max_root_iterations<policy_type>())
{
return policies::raise_evaluation_error<value_type>(
function,
"Unable to locate solution in a reasonable time:"
" either there is no answer to the mode of the distribution"
" or the answer is infinite. Current best guess is %1%", result, policy_type());
}
return result;
}
//
// As above,but confined to the interval [0,1]:
//
template <class Dist>
typename Dist::value_type generic_find_mode_01(const Dist& dist, typename Dist::value_type guess, const char* function)
{
BOOST_MATH_STD_USING
typedef typename Dist::value_type value_type;
typedef typename Dist::policy_type policy_type;
//
// Need to begin by bracketing the maxima of the PDF:
//
value_type maxval;
value_type upper_bound = guess;
value_type lower_bound;
value_type v = pdf(dist, guess);
do
{
maxval = v;
upper_bound = 1 - (1 - upper_bound) / 2;
if(upper_bound == 1)
return 1;
v = pdf(dist, upper_bound);
}while(maxval < v);
lower_bound = upper_bound;
do
{
maxval = v;
lower_bound /= 2;
if(lower_bound < tools::min_value<value_type>())
return 0;
v = pdf(dist, lower_bound);
}while(maxval < v);
boost::uintmax_t max_iter = policies::get_max_root_iterations<policy_type>();
value_type result = tools::brent_find_minima(
pdf_minimizer<Dist>(dist),
lower_bound,
upper_bound,
policies::digits<value_type, policy_type>(),
max_iter).first;
if(max_iter >= policies::get_max_root_iterations<policy_type>())
{
return policies::raise_evaluation_error<value_type>(
function,
"Unable to locate solution in a reasonable time:"
" either there is no answer to the mode of the distribution"
" or the answer is infinite. Current best guess is %1%", result, policy_type());
}
return result;
}
}}} // namespaces
#endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_MODE_HPP

View File

@@ -0,0 +1,91 @@
// Copyright John Maddock 2008.
// 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_DISTIBUTIONS_DETAIL_GENERIC_QUANTILE_HPP
#define BOOST_MATH_DISTIBUTIONS_DETAIL_GENERIC_QUANTILE_HPP
namespace boost{ namespace math{ namespace detail{
template <class Dist>
struct generic_quantile_finder
{
typedef typename Dist::value_type value_type;
typedef typename Dist::policy_type policy_type;
generic_quantile_finder(const Dist& d, value_type t, bool c)
: dist(d), target(t), comp(c) {}
value_type operator()(const value_type& x)
{
return comp ?
value_type(target - cdf(complement(dist, x)))
: value_type(cdf(dist, x) - target);
}
private:
Dist dist;
value_type target;
bool comp;
};
template <class T, class Policy>
inline T check_range_result(const T& x, const Policy& pol, const char* function)
{
if((x >= 0) && (x < tools::min_value<T>()))
return policies::raise_underflow_error<T>(function, 0, pol);
if(x <= -tools::max_value<T>())
return -policies::raise_overflow_error<T>(function, 0, pol);
if(x >= tools::max_value<T>())
return policies::raise_overflow_error<T>(function, 0, pol);
return x;
}
template <class Dist>
typename Dist::value_type generic_quantile(const Dist& dist, const typename Dist::value_type& p, const typename Dist::value_type& guess, bool comp, const char* function)
{
typedef typename Dist::value_type value_type;
typedef typename Dist::policy_type policy_type;
typedef typename policies::normalise<
policy_type,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
//
// Special cases first:
//
if(p == 0)
{
return comp
? check_range_result(range(dist).second, forwarding_policy(), function)
: check_range_result(range(dist).first, forwarding_policy(), function);
}
if(p == 1)
{
return !comp
? check_range_result(range(dist).second, forwarding_policy(), function)
: check_range_result(range(dist).first, forwarding_policy(), function);
}
generic_quantile_finder<Dist> f(dist, p, comp);
tools::eps_tolerance<value_type> tol(policies::digits<value_type, forwarding_policy>() - 3);
boost::uintmax_t max_iter = policies::get_max_root_iterations<forwarding_policy>();
std::pair<value_type, value_type> ir = tools::bracket_and_solve_root(
f, guess, value_type(2), true, tol, max_iter, forwarding_policy());
value_type result = ir.first + (ir.second - ir.first) / 2;
if(max_iter >= policies::get_max_root_iterations<forwarding_policy>())
{
return policies::raise_evaluation_error<value_type>(function, "Unable to locate solution in a reasonable time:"
" either there is no answer to quantile"
" or the answer is infinite. Current best guess is %1%", result, forwarding_policy());
}
return result;
}
}}} // namespaces
#endif // BOOST_MATH_DISTIBUTIONS_DETAIL_GENERIC_QUANTILE_HPP

View File

@@ -0,0 +1,100 @@
// Copyright 2008 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_DISTRIBUTIONS_DETAIL_HG_CDF_HPP
#define BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_CDF_HPP
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/distributions/detail/hypergeometric_pdf.hpp>
namespace boost{ namespace math{ namespace detail{
template <class T, class Policy>
T hypergeometric_cdf_imp(unsigned x, unsigned r, unsigned n, unsigned N, bool invert, const Policy& pol)
{
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:4267)
#endif
BOOST_MATH_STD_USING
T result = 0;
T mode = floor(T(r + 1) * T(n + 1) / (N + 2));
if(x < mode)
{
result = hypergeometric_pdf<T>(x, r, n, N, pol);
T diff = result;
unsigned lower_limit = static_cast<unsigned>((std::max)(0, (int)(n + r) - (int)(N)));
while(diff > (invert ? T(1) : result) * tools::epsilon<T>())
{
diff = T(x) * T((N + x) - n - r) * diff / (T(1 + n - x) * T(1 + r - x));
result += diff;
BOOST_MATH_INSTRUMENT_VARIABLE(x);
BOOST_MATH_INSTRUMENT_VARIABLE(diff);
BOOST_MATH_INSTRUMENT_VARIABLE(result);
if(x == lower_limit)
break;
--x;
}
}
else
{
invert = !invert;
unsigned upper_limit = (std::min)(r, n);
if(x != upper_limit)
{
++x;
result = hypergeometric_pdf<T>(x, r, n, N, pol);
T diff = result;
while((x <= upper_limit) && (diff > (invert ? T(1) : result) * tools::epsilon<T>()))
{
diff = T(n - x) * T(r - x) * diff / (T(x + 1) * T((N + x + 1) - n - r));
result += diff;
++x;
BOOST_MATH_INSTRUMENT_VARIABLE(x);
BOOST_MATH_INSTRUMENT_VARIABLE(diff);
BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
}
}
if(invert)
result = 1 - result;
return result;
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
}
template <class T, class Policy>
inline T hypergeometric_cdf(unsigned x, unsigned r, unsigned n, unsigned N, bool invert, const Policy&)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
value_type result;
result = detail::hypergeometric_cdf_imp<value_type>(x, r, n, N, invert, forwarding_policy());
if(result > 1)
{
result = 1;
}
if(result < 0)
{
result = 0;
}
return policies::checked_narrowing_cast<result_type, forwarding_policy>(result, "boost::math::hypergeometric_cdf<%1%>(%1%,%1%,%1%,%1%)");
}
}}} // namespaces
#endif

View File

@@ -0,0 +1,488 @@
// Copyright 2008 Gautam Sewani
// Copyright 2008 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_DISTRIBUTIONS_DETAIL_HG_PDF_HPP
#define BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_PDF_HPP
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/lanczos.hpp>
#include <boost/math/special_functions/gamma.hpp>
#include <boost/math/special_functions/pow.hpp>
#include <boost/math/special_functions/prime.hpp>
#include <boost/math/policies/error_handling.hpp>
#ifdef BOOST_MATH_INSTRUMENT
#include <typeinfo>
#endif
namespace boost{ namespace math{ namespace detail{
template <class T, class Func>
void bubble_down_one(T* first, T* last, Func f)
{
using std::swap;
T* next = first;
++next;
while((next != last) && (!f(*first, *next)))
{
swap(*first, *next);
++first;
++next;
}
}
template <class T>
struct sort_functor
{
sort_functor(const T* exponents) : m_exponents(exponents){}
bool operator()(int i, int j)
{
return m_exponents[i] > m_exponents[j];
}
private:
const T* m_exponents;
};
template <class T, class Lanczos, class Policy>
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const Lanczos&, const Policy&)
{
BOOST_MATH_STD_USING
BOOST_MATH_INSTRUMENT_FPU
BOOST_MATH_INSTRUMENT_VARIABLE(x);
BOOST_MATH_INSTRUMENT_VARIABLE(r);
BOOST_MATH_INSTRUMENT_VARIABLE(n);
BOOST_MATH_INSTRUMENT_VARIABLE(N);
BOOST_MATH_INSTRUMENT_VARIABLE(typeid(Lanczos).name());
T bases[9] = {
T(n) + static_cast<T>(Lanczos::g()) + 0.5f,
T(r) + static_cast<T>(Lanczos::g()) + 0.5f,
T(N - n) + static_cast<T>(Lanczos::g()) + 0.5f,
T(N - r) + static_cast<T>(Lanczos::g()) + 0.5f,
1 / (T(N) + static_cast<T>(Lanczos::g()) + 0.5f),
1 / (T(x) + static_cast<T>(Lanczos::g()) + 0.5f),
1 / (T(n - x) + static_cast<T>(Lanczos::g()) + 0.5f),
1 / (T(r - x) + static_cast<T>(Lanczos::g()) + 0.5f),
1 / (T(N - n - r + x) + static_cast<T>(Lanczos::g()) + 0.5f)
};
T exponents[9] = {
n + T(0.5f),
r + T(0.5f),
N - n + T(0.5f),
N - r + T(0.5f),
N + T(0.5f),
x + T(0.5f),
n - x + T(0.5f),
r - x + T(0.5f),
N - n - r + x + T(0.5f)
};
int base_e_factors[9] = {
-1, -1, -1, -1, 1, 1, 1, 1, 1
};
int sorted_indexes[9] = {
0, 1, 2, 3, 4, 5, 6, 7, 8
};
#ifdef BOOST_MATH_INSTRUMENT
BOOST_MATH_INSTRUMENT_FPU
for(unsigned i = 0; i < 9; ++i)
{
BOOST_MATH_INSTRUMENT_VARIABLE(i);
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
}
#endif
std::sort(sorted_indexes, sorted_indexes + 9, sort_functor<T>(exponents));
#ifdef BOOST_MATH_INSTRUMENT
BOOST_MATH_INSTRUMENT_FPU
for(unsigned i = 0; i < 9; ++i)
{
BOOST_MATH_INSTRUMENT_VARIABLE(i);
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
}
#endif
do{
exponents[sorted_indexes[0]] -= exponents[sorted_indexes[1]];
bases[sorted_indexes[1]] *= bases[sorted_indexes[0]];
if((bases[sorted_indexes[1]] < tools::min_value<T>()) && (exponents[sorted_indexes[1]] != 0))
{
return 0;
}
base_e_factors[sorted_indexes[1]] += base_e_factors[sorted_indexes[0]];
bubble_down_one(sorted_indexes, sorted_indexes + 9, sort_functor<T>(exponents));
#ifdef BOOST_MATH_INSTRUMENT
for(unsigned i = 0; i < 9; ++i)
{
BOOST_MATH_INSTRUMENT_VARIABLE(i);
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
}
#endif
}while(exponents[sorted_indexes[1]] > 1);
//
// Combine equal powers:
//
int j = 8;
while(exponents[sorted_indexes[j]] == 0) --j;
while(j)
{
while(j && (exponents[sorted_indexes[j-1]] == exponents[sorted_indexes[j]]))
{
bases[sorted_indexes[j-1]] *= bases[sorted_indexes[j]];
exponents[sorted_indexes[j]] = 0;
base_e_factors[sorted_indexes[j-1]] += base_e_factors[sorted_indexes[j]];
bubble_down_one(sorted_indexes + j, sorted_indexes + 9, sort_functor<T>(exponents));
--j;
}
--j;
#ifdef BOOST_MATH_INSTRUMENT
BOOST_MATH_INSTRUMENT_VARIABLE(j);
for(unsigned i = 0; i < 9; ++i)
{
BOOST_MATH_INSTRUMENT_VARIABLE(i);
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
}
#endif
}
#ifdef BOOST_MATH_INSTRUMENT
BOOST_MATH_INSTRUMENT_FPU
for(unsigned i = 0; i < 9; ++i)
{
BOOST_MATH_INSTRUMENT_VARIABLE(i);
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
}
#endif
T result;
BOOST_MATH_INSTRUMENT_VARIABLE(bases[sorted_indexes[0]] * exp(static_cast<T>(base_e_factors[sorted_indexes[0]])));
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[sorted_indexes[0]]);
{
BOOST_FPU_EXCEPTION_GUARD
result = pow(bases[sorted_indexes[0]] * exp(static_cast<T>(base_e_factors[sorted_indexes[0]])), exponents[sorted_indexes[0]]);
}
BOOST_MATH_INSTRUMENT_VARIABLE(result);
for(unsigned i = 1; (i < 9) && (exponents[sorted_indexes[i]] > 0); ++i)
{
BOOST_FPU_EXCEPTION_GUARD
if(result < tools::min_value<T>())
return 0; // short circuit further evaluation
if(exponents[sorted_indexes[i]] == 1)
result *= bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]]));
else if(exponents[sorted_indexes[i]] == 0.5f)
result *= sqrt(bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]])));
else
result *= pow(bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]])), exponents[sorted_indexes[i]]);
BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
result *= Lanczos::lanczos_sum_expG_scaled(static_cast<T>(n + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(r + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - n + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - r + 1))
/
( Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(x + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(n - x + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(r - x + 1))
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - n - r + x + 1)));
BOOST_MATH_INSTRUMENT_VARIABLE(result);
return result;
}
template <class T, class Policy>
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const boost::math::lanczos::undefined_lanczos&, const Policy& pol)
{
BOOST_MATH_STD_USING
return exp(
boost::math::lgamma(T(n + 1), pol)
+ boost::math::lgamma(T(r + 1), pol)
+ boost::math::lgamma(T(N - n + 1), pol)
+ boost::math::lgamma(T(N - r + 1), pol)
- boost::math::lgamma(T(N + 1), pol)
- boost::math::lgamma(T(x + 1), pol)
- boost::math::lgamma(T(n - x + 1), pol)
- boost::math::lgamma(T(r - x + 1), pol)
- boost::math::lgamma(T(N - n - r + x + 1), pol));
}
template <class T>
inline T integer_power(const T& x, int ex)
{
if(ex < 0)
return 1 / integer_power(x, -ex);
switch(ex)
{
case 0:
return 1;
case 1:
return x;
case 2:
return x * x;
case 3:
return x * x * x;
case 4:
return boost::math::pow<4>(x);
case 5:
return boost::math::pow<5>(x);
case 6:
return boost::math::pow<6>(x);
case 7:
return boost::math::pow<7>(x);
case 8:
return boost::math::pow<8>(x);
}
BOOST_MATH_STD_USING
#ifdef __SUNPRO_CC
return pow(x, T(ex));
#else
return pow(x, ex);
#endif
}
template <class T>
struct hypergeometric_pdf_prime_loop_result_entry
{
T value;
const hypergeometric_pdf_prime_loop_result_entry* next;
};
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4510 4512 4610)
#endif
struct hypergeometric_pdf_prime_loop_data
{
const unsigned x;
const unsigned r;
const unsigned n;
const unsigned N;
unsigned prime_index;
unsigned current_prime;
};
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
template <class T>
T hypergeometric_pdf_prime_loop_imp(hypergeometric_pdf_prime_loop_data& data, hypergeometric_pdf_prime_loop_result_entry<T>& result)
{
while(data.current_prime <= data.N)
{
unsigned base = data.current_prime;
int prime_powers = 0;
while(base <= data.N)
{
prime_powers += data.n / base;
prime_powers += data.r / base;
prime_powers += (data.N - data.n) / base;
prime_powers += (data.N - data.r) / base;
prime_powers -= data.N / base;
prime_powers -= data.x / base;
prime_powers -= (data.n - data.x) / base;
prime_powers -= (data.r - data.x) / base;
prime_powers -= (data.N - data.n - data.r + data.x) / base;
base *= data.current_prime;
}
if(prime_powers)
{
T p = integer_power<T>(static_cast<T>(data.current_prime), prime_powers);
if((p > 1) && (tools::max_value<T>() / p < result.value))
{
//
// The next calculation would overflow, use recursion
// to sidestep the issue:
//
hypergeometric_pdf_prime_loop_result_entry<T> t = { p, &result };
data.current_prime = prime(++data.prime_index);
return hypergeometric_pdf_prime_loop_imp<T>(data, t);
}
if((p < 1) && (tools::min_value<T>() / p > result.value))
{
//
// The next calculation would underflow, use recursion
// to sidestep the issue:
//
hypergeometric_pdf_prime_loop_result_entry<T> t = { p, &result };
data.current_prime = prime(++data.prime_index);
return hypergeometric_pdf_prime_loop_imp<T>(data, t);
}
result.value *= p;
}
data.current_prime = prime(++data.prime_index);
}
//
// When we get to here we have run out of prime factors,
// the overall result is the product of all the partial
// results we have accumulated on the stack so far, these
// are in a linked list starting with "data.head" and ending
// with "result".
//
// All that remains is to multiply them together, taking
// care not to overflow or underflow.
//
// Enumerate partial results >= 1 in variable i
// and partial results < 1 in variable j:
//
hypergeometric_pdf_prime_loop_result_entry<T> const *i, *j;
i = &result;
while(i && i->value < 1)
i = i->next;
j = &result;
while(j && j->value >= 1)
j = j->next;
T prod = 1;
while(i || j)
{
while(i && ((prod <= 1) || (j == 0)))
{
prod *= i->value;
i = i->next;
while(i && i->value < 1)
i = i->next;
}
while(j && ((prod >= 1) || (i == 0)))
{
prod *= j->value;
j = j->next;
while(j && j->value >= 1)
j = j->next;
}
}
return prod;
}
template <class T, class Policy>
inline T hypergeometric_pdf_prime_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
{
hypergeometric_pdf_prime_loop_result_entry<T> result = { 1, 0 };
hypergeometric_pdf_prime_loop_data data = { x, r, n, N, 0, prime(0) };
return hypergeometric_pdf_prime_loop_imp<T>(data, result);
}
template <class T, class Policy>
T hypergeometric_pdf_factorial_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
{
BOOST_MATH_STD_USING
BOOST_ASSERT(N <= boost::math::max_factorial<T>::value);
T result = boost::math::unchecked_factorial<T>(n);
T num[3] = {
boost::math::unchecked_factorial<T>(r),
boost::math::unchecked_factorial<T>(N - n),
boost::math::unchecked_factorial<T>(N - r)
};
T denom[5] = {
boost::math::unchecked_factorial<T>(N),
boost::math::unchecked_factorial<T>(x),
boost::math::unchecked_factorial<T>(n - x),
boost::math::unchecked_factorial<T>(r - x),
boost::math::unchecked_factorial<T>(N - n - r + x)
};
int i = 0;
int j = 0;
while((i < 3) || (j < 5))
{
while((j < 5) && ((result >= 1) || (i >= 3)))
{
result /= denom[j];
++j;
}
while((i < 3) && ((result <= 1) || (j >= 5)))
{
result *= num[i];
++i;
}
}
return result;
}
template <class T, class Policy>
inline typename tools::promote_args<T>::type
hypergeometric_pdf(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
value_type result;
if(N <= boost::math::max_factorial<value_type>::value)
{
//
// If N is small enough then we can evaluate the PDF via the factorials
// directly: table lookup of the factorials gives the best performance
// of the methods available:
//
result = detail::hypergeometric_pdf_factorial_imp<value_type>(x, r, n, N, forwarding_policy());
}
else if(N <= boost::math::prime(boost::math::max_prime - 1))
{
//
// If N is no larger than the largest prime number in our lookup table
// (104729) then we can use prime factorisation to evaluate the PDF,
// this is slow but accurate:
//
result = detail::hypergeometric_pdf_prime_imp<value_type>(x, r, n, N, forwarding_policy());
}
else
{
//
// Catch all case - use the lanczos approximation - where available -
// to evaluate the ratio of factorials. This is reasonably fast
// (almost as quick as using logarithmic evaluation in terms of lgamma)
// but only a few digits better in accuracy than using lgamma:
//
result = detail::hypergeometric_pdf_lanczos_imp(value_type(), x, r, n, N, evaluation_type(), forwarding_policy());
}
if(result > 1)
{
result = 1;
}
if(result < 0)
{
result = 0;
}
return policies::checked_narrowing_cast<result_type, forwarding_policy>(result, "boost::math::hypergeometric_pdf<%1%>(%1%,%1%,%1%,%1%)");
}
}}} // namespaces
#endif

View File

@@ -0,0 +1,245 @@
// Copyright 2008 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_DISTRIBUTIONS_DETAIL_HG_QUANTILE_HPP
#define BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_QUANTILE_HPP
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/distributions/detail/hypergeometric_pdf.hpp>
namespace boost{ namespace math{ namespace detail{
template <class T>
inline unsigned round_x_from_p(unsigned x, T p, T cum, T fudge_factor, unsigned lbound, unsigned /*ubound*/, const policies::discrete_quantile<policies::integer_round_down>&)
{
if((p < cum * fudge_factor) && (x != lbound))
{
BOOST_MATH_INSTRUMENT_VARIABLE(x-1);
return --x;
}
return x;
}
template <class T>
inline unsigned round_x_from_p(unsigned x, T p, T cum, T fudge_factor, unsigned /*lbound*/, unsigned ubound, const policies::discrete_quantile<policies::integer_round_up>&)
{
if((cum < p * fudge_factor) && (x != ubound))
{
BOOST_MATH_INSTRUMENT_VARIABLE(x+1);
return ++x;
}
return x;
}
template <class T>
inline unsigned round_x_from_p(unsigned x, T p, T cum, T fudge_factor, unsigned lbound, unsigned ubound, const policies::discrete_quantile<policies::integer_round_inwards>&)
{
if(p >= 0.5)
return round_x_from_p(x, p, cum, fudge_factor, lbound, ubound, policies::discrete_quantile<policies::integer_round_down>());
return round_x_from_p(x, p, cum, fudge_factor, lbound, ubound, policies::discrete_quantile<policies::integer_round_up>());
}
template <class T>
inline unsigned round_x_from_p(unsigned x, T p, T cum, T fudge_factor, unsigned lbound, unsigned ubound, const policies::discrete_quantile<policies::integer_round_outwards>&)
{
if(p >= 0.5)
return round_x_from_p(x, p, cum, fudge_factor, lbound, ubound, policies::discrete_quantile<policies::integer_round_up>());
return round_x_from_p(x, p, cum, fudge_factor, lbound, ubound, policies::discrete_quantile<policies::integer_round_down>());
}
template <class T>
inline unsigned round_x_from_p(unsigned x, T /*p*/, T /*cum*/, T /*fudge_factor*/, unsigned /*lbound*/, unsigned /*ubound*/, const policies::discrete_quantile<policies::integer_round_nearest>&)
{
return x;
}
template <class T>
inline unsigned round_x_from_q(unsigned x, T q, T cum, T fudge_factor, unsigned lbound, unsigned /*ubound*/, const policies::discrete_quantile<policies::integer_round_down>&)
{
if((q * fudge_factor > cum) && (x != lbound))
{
BOOST_MATH_INSTRUMENT_VARIABLE(x-1);
return --x;
}
return x;
}
template <class T>
inline unsigned round_x_from_q(unsigned x, T q, T cum, T fudge_factor, unsigned /*lbound*/, unsigned ubound, const policies::discrete_quantile<policies::integer_round_up>&)
{
if((q < cum * fudge_factor) && (x != ubound))
{
BOOST_MATH_INSTRUMENT_VARIABLE(x+1);
return ++x;
}
return x;
}
template <class T>
inline unsigned round_x_from_q(unsigned x, T q, T cum, T fudge_factor, unsigned lbound, unsigned ubound, const policies::discrete_quantile<policies::integer_round_inwards>&)
{
if(q < 0.5)
return round_x_from_q(x, q, cum, fudge_factor, lbound, ubound, policies::discrete_quantile<policies::integer_round_down>());
return round_x_from_q(x, q, cum, fudge_factor, lbound, ubound, policies::discrete_quantile<policies::integer_round_up>());
}
template <class T>
inline unsigned round_x_from_q(unsigned x, T q, T cum, T fudge_factor, unsigned lbound, unsigned ubound, const policies::discrete_quantile<policies::integer_round_outwards>&)
{
if(q >= 0.5)
return round_x_from_q(x, q, cum, fudge_factor, lbound, ubound, policies::discrete_quantile<policies::integer_round_down>());
return round_x_from_q(x, q, cum, fudge_factor, lbound, ubound, policies::discrete_quantile<policies::integer_round_up>());
}
template <class T>
inline unsigned round_x_from_q(unsigned x, T /*q*/, T /*cum*/, T /*fudge_factor*/, unsigned /*lbound*/, unsigned /*ubound*/, const policies::discrete_quantile<policies::integer_round_nearest>&)
{
return x;
}
template <class T, class Policy>
unsigned hypergeometric_quantile_imp(T p, T q, unsigned r, unsigned n, unsigned N, const Policy& pol)
{
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:4267)
#endif
typedef typename Policy::discrete_quantile_type discrete_quantile_type;
BOOST_MATH_STD_USING
BOOST_FPU_EXCEPTION_GUARD
T result;
T fudge_factor = 1 + tools::epsilon<T>() * ((N <= boost::math::prime(boost::math::max_prime - 1)) ? 50 : 2 * N);
unsigned base = static_cast<unsigned>((std::max)(0, (int)(n + r) - (int)(N)));
unsigned lim = (std::min)(r, n);
BOOST_MATH_INSTRUMENT_VARIABLE(p);
BOOST_MATH_INSTRUMENT_VARIABLE(q);
BOOST_MATH_INSTRUMENT_VARIABLE(r);
BOOST_MATH_INSTRUMENT_VARIABLE(n);
BOOST_MATH_INSTRUMENT_VARIABLE(N);
BOOST_MATH_INSTRUMENT_VARIABLE(fudge_factor);
BOOST_MATH_INSTRUMENT_VARIABLE(base);
BOOST_MATH_INSTRUMENT_VARIABLE(lim);
if(p <= 0.5)
{
unsigned x = base;
result = hypergeometric_pdf<T>(x, r, n, N, pol);
T diff = result;
if (diff == 0)
{
++x;
// We want to skip through x values as fast as we can until we start getting non-zero values,
// otherwise we're just making lots of expensive PDF calls:
T log_pdf = boost::math::lgamma(static_cast<T>(n + 1), pol)
+ boost::math::lgamma(static_cast<T>(r + 1), pol)
+ boost::math::lgamma(static_cast<T>(N - n + 1), pol)
+ boost::math::lgamma(static_cast<T>(N - r + 1), pol)
- boost::math::lgamma(static_cast<T>(N + 1), pol)
- boost::math::lgamma(static_cast<T>(x + 1), pol)
- boost::math::lgamma(static_cast<T>(n - x + 1), pol)
- boost::math::lgamma(static_cast<T>(r - x + 1), pol)
- boost::math::lgamma(static_cast<T>(N - n - r + x + 1), pol);
while (log_pdf < tools::log_min_value<T>())
{
log_pdf += -log(static_cast<T>(x + 1)) + log(static_cast<T>(n - x)) + log(static_cast<T>(r - x)) - log(static_cast<T>(N - n - r + x + 1));
++x;
}
// By the time we get here, log_pdf may be fairly inaccurate due to
// roundoff errors, get a fresh PDF calculation before proceding:
diff = hypergeometric_pdf<T>(x, r, n, N, pol);
}
while(result < p)
{
diff = (diff > tools::min_value<T>() * 8)
? T(n - x) * T(r - x) * diff / (T(x + 1) * T(N + x + 1 - n - r))
: hypergeometric_pdf<T>(x + 1, r, n, N, pol);
if(result + diff / 2 > p)
break;
++x;
result += diff;
#ifdef BOOST_MATH_INSTRUMENT
if(diff != 0)
{
BOOST_MATH_INSTRUMENT_VARIABLE(x);
BOOST_MATH_INSTRUMENT_VARIABLE(diff);
BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
#endif
}
return round_x_from_p(x, p, result, fudge_factor, base, lim, discrete_quantile_type());
}
else
{
unsigned x = lim;
result = 0;
T diff = hypergeometric_pdf<T>(x, r, n, N, pol);
if (diff == 0)
{
// We want to skip through x values as fast as we can until we start getting non-zero values,
// otherwise we're just making lots of expensive PDF calls:
--x;
T log_pdf = boost::math::lgamma(static_cast<T>(n + 1), pol)
+ boost::math::lgamma(static_cast<T>(r + 1), pol)
+ boost::math::lgamma(static_cast<T>(N - n + 1), pol)
+ boost::math::lgamma(static_cast<T>(N - r + 1), pol)
- boost::math::lgamma(static_cast<T>(N + 1), pol)
- boost::math::lgamma(static_cast<T>(x + 1), pol)
- boost::math::lgamma(static_cast<T>(n - x + 1), pol)
- boost::math::lgamma(static_cast<T>(r - x + 1), pol)
- boost::math::lgamma(static_cast<T>(N - n - r + x + 1), pol);
while (log_pdf < tools::log_min_value<T>())
{
log_pdf += log(static_cast<T>(x)) - log(static_cast<T>(n - x + 1)) - log(static_cast<T>(r - x + 1)) + log(static_cast<T>(N - n - r + x));
--x;
}
// By the time we get here, log_pdf may be fairly inaccurate due to
// roundoff errors, get a fresh PDF calculation before proceding:
diff = hypergeometric_pdf<T>(x, r, n, N, pol);
}
while(result + diff / 2 < q)
{
result += diff;
diff = (diff > tools::min_value<T>() * 8)
? x * T(N + x - n - r) * diff / (T(1 + n - x) * T(1 + r - x))
: hypergeometric_pdf<T>(x - 1, r, n, N, pol);
--x;
#ifdef BOOST_MATH_INSTRUMENT
if(diff != 0)
{
BOOST_MATH_INSTRUMENT_VARIABLE(x);
BOOST_MATH_INSTRUMENT_VARIABLE(diff);
BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
#endif
}
return round_x_from_q(x, q, result, fudge_factor, base, lim, discrete_quantile_type());
}
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
}
template <class T, class Policy>
inline unsigned hypergeometric_quantile(T p, T q, unsigned r, unsigned n, unsigned N, const Policy&)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::assert_undefined<> >::type forwarding_policy;
return detail::hypergeometric_quantile_imp<value_type>(p, q, r, n, N, forwarding_policy());
}
}}} // namespaces
#endif

View File

@@ -0,0 +1,571 @@
// 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, bool c)
: dist(d), target(p), comp(c) {}
value_type operator()(value_type const& x)
{
return comp ? value_type(target - cdf(complement(dist, x))) : value_type(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,
bool comp,
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, comp);
//
// Max bounds of the distribution:
//
value_type min_bound, max_bound;
boost::math::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;
if(a == b)
return b; // can't go any higher!
}
else
{
b = a;
a = (std::max)(value_type(b - 1), value_type(0));
if(a < min_bound)
a = min_bound;
fa = f(a);
--count;
if(fa == 0)
return a;
if(a == b)
return a; // We can't go any lower than this!
}
}
}
//
// 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)(value_type(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)(value_type(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((boost::math::sign)(fb) == (boost::math::sign)(fa))
{
if(fa < 0)
{
//
// Zero is to the right of x2, so walk upwards
// until we find it:
//
while(((boost::math::sign)(fb) == (boost::math::sign)(fa)) && (a != b))
{
if(count == 0)
return 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(((boost::math::sign)(fb) == (boost::math::sign)(fa)) && (a != b))
{
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)
return 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;
if(a == b)
return b; // Ran out of bounds trying to bracket - there is no answer!
//
// 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;
}
//
// Some special routine for rounding up and down:
// We want to check and see if we are very close to an integer, and if so test to see if
// that integer is an exact root of the cdf. We do this because our root finder only
// guarantees to find *a root*, and there can sometimes be many consecutive floating
// point values which are all roots. This is especially true if the target probability
// is very close 1.
//
template <class Dist>
inline typename Dist::value_type round_to_floor(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c)
{
BOOST_MATH_STD_USING
typename Dist::value_type cc = ceil(result);
typename Dist::value_type pp = cc <= support(d).second ? c ? cdf(complement(d, cc)) : cdf(d, cc) : 1;
if(pp == p)
result = cc;
else
result = floor(result);
//
// Now find the smallest integer <= result for which we get an exact root:
//
while(result != 0)
{
cc = result - 1;
if(cc < support(d).first)
break;
pp = c ? cdf(complement(d, cc)) : cdf(d, cc);
if(pp == p)
result = cc;
else if(c ? pp > p : pp < p)
break;
result -= 1;
}
return result;
}
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127)
#endif
template <class Dist>
inline typename Dist::value_type round_to_ceil(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c)
{
BOOST_MATH_STD_USING
typename Dist::value_type cc = floor(result);
typename Dist::value_type pp = cc >= support(d).first ? c ? cdf(complement(d, cc)) : cdf(d, cc) : 0;
if(pp == p)
result = cc;
else
result = ceil(result);
//
// Now find the largest integer >= result for which we get an exact root:
//
while(true)
{
cc = result + 1;
if(cc > support(d).second)
break;
pp = c ? cdf(complement(d, cc)) : cdf(d, cc);
if(pp == p)
result = cc;
else if(c ? pp < p : pp > p)
break;
result += 1;
}
return result;
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
//
// 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,
typename Dist::value_type p,
bool c,
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 > 0.5)
{
p = 1 - p;
c = !c;
}
typename Dist::value_type pp = c ? 1 - p : p;
if(pp <= pdf(dist, 0))
return 0;
return do_inverse_discrete_quantile(
dist,
p,
c,
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,
bool c,
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
typename Dist::value_type pp = c ? 1 - p : p;
if(pp <= pdf(dist, 0))
return 0;
//
// What happens next depends on whether we're looking for an
// upper or lower quantile:
//
if(pp < 0.5f)
return round_to_floor(dist, do_inverse_discrete_quantile(
dist,
p,
c,
(guess < 1 ? value_type(1) : (value_type)floor(guess)),
multiplier,
adder,
tools::equal_floor(),
max_iter), p, c);
// else:
return round_to_ceil(dist, do_inverse_discrete_quantile(
dist,
p,
c,
(value_type)ceil(guess),
multiplier,
adder,
tools::equal_ceil(),
max_iter), p, c);
}
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
bool c,
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
typename Dist::value_type pp = c ? 1 - p : p;
if(pp <= pdf(dist, 0))
return 0;
//
// What happens next depends on whether we're looking for an
// upper or lower quantile:
//
if(pp < 0.5f)
return round_to_ceil(dist, do_inverse_discrete_quantile(
dist,
p,
c,
ceil(guess),
multiplier,
adder,
tools::equal_ceil(),
max_iter), p, c);
// else:
return round_to_floor(dist, do_inverse_discrete_quantile(
dist,
p,
c,
(guess < 1 ? value_type(1) : floor(guess)),
multiplier,
adder,
tools::equal_floor(),
max_iter), p, c);
}
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
bool c,
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
typename Dist::value_type pp = c ? 1 - p : p;
if(pp <= pdf(dist, 0))
return 0;
return round_to_floor(dist, do_inverse_discrete_quantile(
dist,
p,
c,
(guess < 1 ? value_type(1) : floor(guess)),
multiplier,
adder,
tools::equal_floor(),
max_iter), p, c);
}
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
bool c,
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
typename Dist::value_type pp = c ? 1 - p : p;
if(pp <= pdf(dist, 0))
return 0;
return round_to_ceil(dist, do_inverse_discrete_quantile(
dist,
p,
c,
ceil(guess),
multiplier,
adder,
tools::equal_ceil(),
max_iter), p, c);
}
template <class Dist>
inline typename Dist::value_type
inverse_discrete_quantile(
const Dist& dist,
const typename Dist::value_type& p,
bool c,
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
typename Dist::value_type pp = c ? 1 - p : p;
if(pp <= 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 round_to_floor(dist, do_inverse_discrete_quantile(
dist,
p,
c,
(guess < 0.5f ? value_type(1.5f) : floor(guess + 0.5f) + 0.5f),
multiplier,
adder,
tools::equal_nearest_integer(),
max_iter) + 0.5f, p, c);
}
}}} // namespaces
#endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE

View File

@@ -0,0 +1,275 @@
// 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 <boost/config/no_tr1/cmath.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4127) // conditional expression is constant
# 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) || !(boost::math::isfinite)(l))
{
*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) || (boost::math::isnan)(x))
{
*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 l_lambda = 1)
: m_lambda(l_lambda)
{
RealType err;
detail::verify_lambda("boost::math::exponential_distribution<%1%>::exponential_distribution", l_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.
if (std::numeric_limits<RealType>::has_infinity)
{
return std::pair<RealType, RealType>(static_cast<RealType>(0), std::numeric_limits<RealType>::infinity()); // 0 to + infinity.
}
else
{
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // 0 to + max
}
}
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;
using boost::math::tools::min_value;
return std::pair<RealType, RealType>(min_value<RealType>(), max_value<RealType>());
// min_value<RealType>() to avoid a discontinuity at x = 0.
}
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 = 0;
if(0 == detail::verify_lambda(function, lambda, &result, Policy()))
return result;
if(0 == detail::verify_exp_x(function, x, &result, Policy()))
return result;
// Workaround for VC11/12 bug:
if ((boost::math::isinf)(x))
return 0;
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 = 0;
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 = 0;
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 = 0;
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;
// Workaround for VC11/12 bug:
if (c.param >= tools::max_value<RealType>())
return 0;
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 = 0;
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 = 0;
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 = 0;
RealType lambda = dist.lambda();
if(0 == detail::verify_lambda("boost::math::standard_deviation(const exponential_distribution<%1%>&)", lambda, &result, Policy()))
return result;
return 1 / lambda;
}
template <class RealType, class Policy>
inline RealType mode(const exponential_distribution<RealType, Policy>& /*dist*/)
{
return 0;
}
template <class RealType, class Policy>
inline RealType median(const exponential_distribution<RealType, Policy>& dist)
{
using boost::math::constants::ln_two;
return ln_two<RealType>() / dist.lambda(); // ln(2) / lambda
}
template <class RealType, class Policy>
inline RealType skewness(const exponential_distribution<RealType, Policy>& /*dist*/)
{
return 2;
}
template <class RealType, class Policy>
inline RealType kurtosis(const exponential_distribution<RealType, Policy>& /*dist*/)
{
return 9;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const exponential_distribution<RealType, Policy>& /*dist*/)
{
return 6;
}
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_EXPONENTIAL_HPP

View File

@@ -0,0 +1,300 @@
// 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 <boost/config/no_tr1/cmath.hpp>
//
// 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) || !(boost::math::isfinite)(b))
{
*presult = policies::raise_domain_error<RealType>(
function,
"The scale parameter \"b\" must be finite and > 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());
detail::check_finite("boost::math::extreme_value_distribution<%1%>::extreme_value_distribution", a, &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>(
std::numeric_limits<RealType>::has_infinity ? -std::numeric_limits<RealType>::infinity() : -max_value<RealType>(),
std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : 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
static const char* function = "boost::math::pdf(const extreme_value_distribution<%1%>&, %1%)";
RealType a = dist.location();
RealType b = dist.scale();
RealType result = 0;
if(0 == detail::verify_scale_b(function, b, &result, Policy()))
return result;
if(0 == detail::check_finite(function, a, &result, Policy()))
return result;
if((boost::math::isinf)(x))
return 0.0f;
if(0 == detail::check_x(function, x, &result, Policy()))
return result;
RealType e = (a - x) / b;
if(e < tools::log_max_value<RealType>())
result = exp(e) * exp(-exp(e)) / b;
// else.... result *must* be zero since exp(e) is infinite...
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
static const char* function = "boost::math::cdf(const extreme_value_distribution<%1%>&, %1%)";
if((boost::math::isinf)(x))
return x < 0 ? 0.0f : 1.0f;
RealType a = dist.location();
RealType b = dist.scale();
RealType result = 0;
if(0 == detail::verify_scale_b(function, b, &result, Policy()))
return result;
if(0 == detail::check_finite(function, a, &result, Policy()))
return result;
if(0 == detail::check_finite(function, a, &result, Policy()))
return result;
if(0 == detail::check_x("boost::math::cdf(const extreme_value_distribution<%1%>&, %1%)", x, &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 = 0;
if(0 == detail::verify_scale_b(function, b, &result, Policy()))
return result;
if(0 == detail::check_finite(function, a, &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
static const char* function = "boost::math::cdf(const extreme_value_distribution<%1%>&, %1%)";
if((boost::math::isinf)(c.param))
return c.param < 0 ? 1.0f : 0.0f;
RealType a = c.dist.location();
RealType b = c.dist.scale();
RealType result = 0;
if(0 == detail::verify_scale_b(function, b, &result, Policy()))
return result;
if(0 == detail::check_finite(function, a, &result, Policy()))
return result;
if(0 == detail::check_x(function, c.param, &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 = 0;
if(0 == detail::verify_scale_b(function, b, &result, Policy()))
return result;
if(0 == detail::check_finite(function, a, &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 = 0;
if(0 == detail::verify_scale_b("boost::math::mean(const extreme_value_distribution<%1%>&)", b, &result, Policy()))
return result;
if(0 == detail::check_scale("boost::math::mean(const extreme_value_distribution<%1%>&)", a, &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 = 0;
if(0 == detail::verify_scale_b("boost::math::standard_deviation(const extreme_value_distribution<%1%>&)", b, &result, Policy()))
return result;
if(0 == detail::check_scale("boost::math::standard_deviation(const extreme_value_distribution<%1%>&)", dist.location(), &result, Policy()))
return result;
return constants::pi<RealType>() * b / sqrt(static_cast<RealType>(6));
}
template <class RealType, class Policy>
inline RealType mode(const extreme_value_distribution<RealType, Policy>& dist)
{
return dist.location();
}
template <class RealType, class Policy>
inline RealType median(const extreme_value_distribution<RealType, Policy>& dist)
{
using constants::ln_ln_two;
return dist.location() - dist.scale() * ln_ln_two<RealType>();
}
template <class RealType, class Policy>
inline RealType skewness(const extreme_value_distribution<RealType, Policy>& /*dist*/)
{
//
// This is 12 * sqrt(6) * zeta(3) / pi^3:
// See http://mathworld.wolfram.com/ExtremeValueDistribution.html
//
return static_cast<RealType>(1.1395470994046486574927930193898461120875997958366L);
}
template <class RealType, class Policy>
inline RealType kurtosis(const extreme_value_distribution<RealType, Policy>& /*dist*/)
{
// See http://mathworld.wolfram.com/ExtremeValueDistribution.html
return RealType(27) / 5;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const extreme_value_distribution<RealType, Policy>& /*dist*/)
{
// See http://mathworld.wolfram.com/ExtremeValueDistribution.html
return RealType(12) / 5;
}
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_EXTREME_VALUE_HPP

View File

@@ -0,0 +1,146 @@
// 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>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/policies/error_handling.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
)
{
#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
// Will fail to compile here if try to use with a distribution without scale & location,
// for example pareto, and many others. These tests are disabled by the pp-logic
// above if the compiler doesn't support the SFINAE tricks used in the traits class.
BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value);
BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value);
#endif
static const char* function = "boost::math::find_location<Dist, Policy>&, %1%)";
if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, pol);
}
if(!(boost::math::isfinite)(z))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "z parameter was %1%, but must be finite!", z, pol);
}
if(!(boost::math::isfinite)(scale))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "scale parameter was %1%, but must be finite!", scale, pol);
}
//cout << "z " << z << ", p " << p << ", quantile(Dist(), p) "
// << quantile(Dist(), p) << ", quan * scale " << quantile(Dist(), p) * scale << endl;
return z - (quantile(Dist(), p) * scale);
} // find_location
template <class Dist>
inline // with default policy.
typename Dist::value_type find_location( // For example, normal mean.
typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p.
// For example, a nominal minimum acceptable z, so that p * 100 % are > z
typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z.
typename Dist::value_type scale) // scale parameter, for example, normal standard deviation.
{ // Forward to find_location with default policy.
return (find_location<Dist>(z, p, scale, policies::policy<>()));
} // find_location
// So the user can start from the complement q = (1 - p) of the probability p,
// for example, l = find_location<normal>(complement(z, q, sd));
template <class Dist, class Real1, class Real2, class Real3>
inline typename Dist::value_type find_location( // Default policy.
complemented3_type<Real1, Real2, Real3> const& c)
{
static const char* function = "boost::math::find_location<Dist, Policy>&, %1%)";
typename Dist::value_type p = c.param1;
if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, policies::policy<>());
}
typename Dist::value_type z = c.dist;
if(!(boost::math::isfinite)(z))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "z parameter was %1%, but must be finite!", z, policies::policy<>());
}
typename Dist::value_type scale = c.param2;
if(!(boost::math::isfinite)(scale))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "scale parameter was %1%, but must be finite!", scale, policies::policy<>());
}
// cout << "z " << c.dist << ", quantile (Dist(), " << c.param1 << ") * scale " << c.param2 << endl;
return z - quantile(Dist(), p) * scale;
} // find_location complement
template <class Dist, class Real1, class Real2, class Real3, class Real4>
inline typename Dist::value_type find_location( // Explicit policy.
complemented4_type<Real1, Real2, Real3, Real4> const& c)
{
static const char* function = "boost::math::find_location<Dist, Policy>&, %1%)";
typename Dist::value_type p = c.param1;
if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, c.param3);
}
typename Dist::value_type z = c.dist;
if(!(boost::math::isfinite)(z))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "z parameter was %1%, but must be finite!", z, c.param3);
}
typename Dist::value_type scale = c.param2;
if(!(boost::math::isfinite)(scale))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "scale parameter was %1%, but must be finite!", scale, c.param3);
}
// cout << "z " << c.dist << ", quantile (Dist(), " << c.param1 << ") * scale " << c.param2 << endl;
return z - quantile(Dist(), p) * scale;
} // find_location complement
} // namespace boost
} // namespace math
#endif // BOOST_STATS_FIND_LOCATION_HPP

View File

@@ -0,0 +1,211 @@
// 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>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/policies/error_handling.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
)
{
#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value);
BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value);
#endif
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;
#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value);
BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value);
#endif
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;
#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value);
BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value);
#endif
static const char* function = "boost::math::find_scale<Dist, Policy>(complement(%1%, %1%, %1%, Policy))";
// Checks on arguments, as not complemented version,
// default policy policies::policy<>().
typename Dist::value_type q = c.param1;
if(!(boost::math::isfinite)(q) || (q < 0) || (q > 1))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "Probability parameter was %1%, but must be >= 0 and <= 1!", q, policies::policy<>());
}
typename Dist::value_type z = c.dist;
if(!(boost::math::isfinite)(z))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "find_scale z parameter was %1%, but must be finite!", z, policies::policy<>());
}
typename Dist::value_type location = c.param2;
if(!(boost::math::isfinite)(location))
{
return policies::raise_domain_error<typename Dist::value_type>(
function, "find_scale location parameter was %1%, but must be finite!", location, policies::policy<>());
}
typename Dist::value_type result =
(z - location) // difference between desired x and current location.
/ quantile(complement(Dist(), q));
// ( z - location) / (quantile(complement(Dist(), q))
if (result <= 0)
{ // If policy isn't to throw, return the scale <= 0.
policies::raise_evaluation_error<typename Dist::value_type>(function,
"Computed scale (%1%) is <= 0!" " Was the complement intended?",
result, policies::policy<>()); // This is only the default policy - also Want a version with Policy here.
}
return result;
} // template <class Dist, class Real1, class Real2, class Real3> typename Dist::value_type find_scale
} // namespace boost
} // namespace math
#endif // BOOST_STATS_FIND_SCALE_HPP

View File

@@ -0,0 +1,387 @@
// 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>(static_cast<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>(static_cast<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 = 0;
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 = 0;
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 = 0;
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;
// With optimizations turned on, gcc wrongly warns about y being used
// uninitializated unless we initialize it to something:
RealType x, y(0);
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 = 0;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
if(false == detail::check_df(
function, df1, &error_result, Policy())
&& detail::check_df(
function, df2, &error_result, Policy()))
return error_result;
if(df2 <= 8)
{
return policies::raise_domain_error<RealType>(
function, "Second degree of freedom was %1% but must be > 8 in order for the distribution to have a kutosis.", df2, Policy());
}
RealType df2_2 = df2 * df2;
RealType df1_2 = df1 * df1;
RealType n = -16 + 20 * df2 - 8 * df2_2 + df2_2 * df2 + 44 * df1 - 32 * df2 * df1 + 5 * df2_2 * df1 - 22 * df1_2 + 5 * df2 * df1_2;
n *= 12;
RealType d = df1 * (df2 - 6) * (df2 - 8) * (df1 + df2 - 2);
return n / d;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_MATH_DISTRIBUTIONS_FISHER_F_HPP

View File

@@ -0,0 +1,153 @@
// fwd.hpp Forward declarations of Boost.Math distributions.
// Copyright Paul A. Bristow 2007, 2010, 2012, 2014.
// 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
// 33 distributions at Boost 1.9.1 after adding hyperexpon and arcsine
namespace boost{ namespace math{
template <class RealType, class Policy>
class arcsine_distribution;
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 geometric_distribution;
template <class RealType, class Policy>
class hyperexponential_distribution;
template <class RealType, class Policy>
class hypergeometric_distribution;
template <class RealType, class Policy>
class inverse_chi_squared_distribution;
template <class RealType, class Policy>
class inverse_gamma_distribution;
template <class RealType, class Policy>
class inverse_gaussian_distribution;
template <class RealType, class Policy>
class laplace_distribution;
template <class RealType, class Policy>
class logistic_distribution;
template <class RealType, class Policy>
class lognormal_distribution;
template <class RealType, class Policy>
class negative_binomial_distribution;
template <class RealType, class Policy>
class non_central_beta_distribution;
template <class RealType, class Policy>
class non_central_chi_squared_distribution;
template <class RealType, class Policy>
class non_central_f_distribution;
template <class RealType, class Policy>
class non_central_t_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 skew_normal_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::arcsine_distribution<Type, Policy> arcsine;\
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::geometric_distribution<Type, Policy> geometric;\
typedef boost::math::hypergeometric_distribution<Type, Policy> hypergeometric;\
typedef boost::math::inverse_chi_squared_distribution<Type, Policy> inverse_chi_squared;\
typedef boost::math::inverse_gaussian_distribution<Type, Policy> inverse_gaussian;\
typedef boost::math::inverse_gamma_distribution<Type, Policy> inverse_gamma;\
typedef boost::math::laplace_distribution<Type, Policy> laplace;\
typedef boost::math::logistic_distribution<Type, Policy> logistic;\
typedef boost::math::lognormal_distribution<Type, Policy> lognormal;\
typedef boost::math::negative_binomial_distribution<Type, Policy> negative_binomial;\
typedef boost::math::non_central_beta_distribution<Type, Policy> non_central_beta;\
typedef boost::math::non_central_chi_squared_distribution<Type, Policy> non_central_chi_squared;\
typedef boost::math::non_central_f_distribution<Type, Policy> non_central_f;\
typedef boost::math::non_central_t_distribution<Type, Policy> non_central_t;\
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::skew_normal_distribution<Type, Policy> skew_normal;\
typedef boost::math::students_t_distribution<Type, Policy> students_t;\
typedef boost::math::triangular_distribution<Type, Policy> triangular;\
typedef boost::math::uniform_distribution<Type, Policy> uniform;\
typedef boost::math::weibull_distribution<Type, Policy> weibull;
#endif // BOOST_MATH_DISTRIBUTIONS_FWD_HPP

View File

@@ -0,0 +1,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)
#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 l_shape, RealType l_scale = 1)
: m_shape(l_shape), m_scale(l_scale)
{
RealType result;
detail::check_gamma("boost::math::gamma_distribution<%1%>::gamma_distribution", l_scale, l_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>(static_cast<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;
using boost::math::tools::min_value;
return std::pair<RealType, RealType>(min_value<RealType>(), 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 = 0;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
if(false == detail::check_gamma(function, scale, shape, &result, Policy()))
return result;
result = 6 / shape;
return result;
}
template <class RealType, class Policy>
inline RealType kurtosis(const gamma_distribution<RealType, Policy>& dist)
{
return kurtosis_excess(dist) + 3;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_GAMMA_HPP

View File

@@ -0,0 +1,516 @@
// boost\math\distributions\geometric.hpp
// Copyright John Maddock 2010.
// Copyright Paul A. Bristow 2010.
// 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)
// geometric distribution is a discrete probability distribution.
// It expresses the probability distribution of the number (k) of
// events, occurrences, failures or arrivals before the first success.
// supported on the set {0, 1, 2, 3...}
// Note that the set includes zero (unlike some definitions that start at one).
// 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 geometric distribution
// (like others including the binomial, geometric & 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/geometric_distribution
// http://documents.wolfram.com/v5/Add-onsLinks/StandardPackages/Statistics/DiscreteDistributions.html
// http://mathworld.wolfram.com/GeometricDistribution.html
#ifndef BOOST_MATH_SPECIAL_GEOMETRIC_HPP
#define BOOST_MATH_SPECIAL_GEOMETRIC_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 geometric_detail
{
// Common error checking routines for geometric distribution function:
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& p, RealType* result, const Policy& pol)
{
return check_success_fraction(function, p, result, pol);
}
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, 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, RealType p, RealType prob, RealType* result, const Policy& pol)
{
if((check_dist(function, p, result, pol) && detail::check_probability(function, prob, result, pol)) == false)
{
return false;
}
return true;
} // check_dist_and_prob
} // namespace geometric_detail
template <class RealType = double, class Policy = policies::policy<> >
class geometric_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
geometric_distribution(RealType p) : m_p(p)
{ // Constructor stores success_fraction p.
RealType result;
geometric_detail::check_dist(
"geometric_distribution<%1%>::geometric_distribution",
m_p, // Check success_fraction 0 <= p <= 1.
&result, Policy());
} // geometric_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 = 1 (for compatibility with negative binomial?).
return 1;
}
// Parameter estimation.
// (These are copies of negative_binomial distribution with successes = 1).
static RealType find_lower_bound_on_p(
RealType trials,
RealType alpha) // alpha 0.05 equivalent to 95% for one-sided test.
{
static const char* function = "boost::math::geometric<%1%>::find_lower_bound_on_p";
RealType result = 0; // of error checks.
RealType successes = 1;
RealType failures = trials - successes;
if(false == detail::check_probability(function, alpha, &result, Policy())
&& geometric_detail::check_dist_and_k(
function, 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 alpha) // alpha 0.05 equivalent to 95% for one-sided test.
{
static const char* function = "boost::math::geometric<%1%>::find_upper_bound_on_p";
RealType result = 0; // of error checks.
RealType successes = 1;
RealType failures = trials - successes;
if(false == geometric_detail::check_dist_and_k(
function, 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::geometric<%1%>::find_minimum_number_of_trials";
// Error checks:
RealType result = 0;
if(false == geometric_detail::check_dist_and_k(
function, 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::geometric<%1%>::find_maximum_number_of_trials";
// Error checks:
RealType result = 0;
if(false == geometric_detail::check_dist_and_k(
function, 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 fixed at unity.
RealType m_p; // success_fraction
}; // template <class RealType, class Policy> class geometric_distribution
typedef geometric_distribution<double> geometric; // Reserved name of type double.
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const geometric_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), max_value<RealType>()); // max_integer?
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const geometric_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>(static_cast<RealType>(0), max_value<RealType>()); // max_integer?
}
template <class RealType, class Policy>
inline RealType mean(const geometric_distribution<RealType, Policy>& dist)
{ // Mean of geometric distribution = (1-p)/p.
return (1 - dist.success_fraction() ) / dist.success_fraction();
} // mean
// median implemented via quantile(half) in derived accessors.
template <class RealType, class Policy>
inline RealType mode(const geometric_distribution<RealType, Policy>&)
{ // Mode of geometric distribution = zero.
BOOST_MATH_STD_USING // ADL of std functions.
return 0;
} // mode
template <class RealType, class Policy>
inline RealType variance(const geometric_distribution<RealType, Policy>& dist)
{ // Variance of Binomial distribution = (1-p) / p^2.
return (1 - dist.success_fraction())
/ (dist.success_fraction() * dist.success_fraction());
} // variance
template <class RealType, class Policy>
inline RealType skewness(const geometric_distribution<RealType, Policy>& dist)
{ // skewness of geometric distribution = 2-p / (sqrt(r(1-p))
BOOST_MATH_STD_USING // ADL of std functions.
RealType p = dist.success_fraction();
return (2 - p) / sqrt(1 - p);
} // skewness
template <class RealType, class Policy>
inline RealType kurtosis(const geometric_distribution<RealType, Policy>& dist)
{ // kurtosis of geometric distribution
// http://en.wikipedia.org/wiki/geometric is kurtosis_excess so add 3
RealType p = dist.success_fraction();
return 3 + (p*p - 6*p + 6) / (1 - p);
} // kurtosis
template <class RealType, class Policy>
inline RealType kurtosis_excess(const geometric_distribution<RealType, Policy>& dist)
{ // kurtosis excess of geometric distribution
// http://mathworld.wolfram.com/Kurtosis.html table of kurtosis_excess
RealType p = dist.success_fraction();
return (p*p - 6*p + 6) / (1 - p);
} // kurtosis_excess
// RealType standard_deviation(const geometric_distribution<RealType, Policy>& dist)
// standard_deviation provided by derived accessors.
// RealType hazard(const geometric_distribution<RealType, Policy>& dist)
// hazard of geometric distribution provided by derived accessors.
// RealType chf(const geometric_distribution<RealType, Policy>& dist)
// chf of geometric distribution provided by derived accessors.
template <class RealType, class Policy>
inline RealType pdf(const geometric_distribution<RealType, Policy>& dist, const RealType& k)
{ // Probability Density/Mass Function.
BOOST_FPU_EXCEPTION_GUARD
BOOST_MATH_STD_USING // For ADL of math functions.
static const char* function = "boost::math::pdf(const geometric_distribution<%1%>&, %1%)";
RealType p = dist.success_fraction();
RealType result = 0;
if(false == geometric_detail::check_dist_and_k(
function,
p,
k,
&result, Policy()))
{
return result;
}
if (k == 0)
{
return p; // success_fraction
}
RealType q = 1 - p; // Inaccurate for small p?
// So try to avoid inaccuracy for large or small p.
// but has little effect > last significant bit.
//cout << "p * pow(q, k) " << result << endl; // seems best whatever p
//cout << "exp(p * k * log1p(-p)) " << p * exp(k * log1p(-p)) << endl;
//if (p < 0.5)
//{
// result = p * pow(q, k);
//}
//else
//{
// result = p * exp(k * log1p(-p));
//}
result = p * pow(q, k);
return result;
} // geometric_pdf
template <class RealType, class Policy>
inline RealType cdf(const geometric_distribution<RealType, Policy>& dist, const RealType& k)
{ // Cumulative Distribution Function of geometric.
static const char* function = "boost::math::cdf(const geometric_distribution<%1%>&, %1%)";
// 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();
// Error check:
RealType result = 0;
if(false == geometric_detail::check_dist_and_k(
function,
p,
k,
&result, Policy()))
{
return result;
}
if(k == 0)
{
return p; // success_fraction
}
//RealType q = 1 - p; // Bad for small p
//RealType probability = 1 - std::pow(q, k+1);
RealType z = boost::math::log1p(-p, Policy()) * (k + 1);
RealType probability = -boost::math::expm1(z, Policy());
return probability;
} // cdf Cumulative Distribution Function geometric.
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<geometric_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function geometric.
BOOST_MATH_STD_USING
static const char* function = "boost::math::cdf(const geometric_distribution<%1%>&, %1%)";
// 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;
geometric_distribution<RealType, Policy> const& dist = c.dist;
RealType p = dist.success_fraction();
// Error check:
RealType result = 0;
if(false == geometric_detail::check_dist_and_k(
function,
p,
k,
&result, Policy()))
{
return result;
}
RealType z = boost::math::log1p(-p, Policy()) * (k+1);
RealType probability = exp(z);
return probability;
} // cdf Complemented Cumulative Distribution Function geometric.
template <class RealType, class Policy>
inline RealType quantile(const geometric_distribution<RealType, Policy>& dist, const RealType& x)
{ // Quantile, percentile/100 or Percent Point geometric function.
// Return the number of expected failures k for a given probability p.
// Inverse cumulative Distribution Function or Quantile (percentile / 100) of geometric Probability.
// k argument may be integral, signed, or unsigned, or floating point.
static const char* function = "boost::math::quantile(const geometric_distribution<%1%>&, %1%)";
BOOST_MATH_STD_USING // ADL of std functions.
RealType success_fraction = dist.success_fraction();
// Check dist and x.
RealType result = 0;
if(false == geometric_detail::check_dist_and_prob
(function, success_fraction, x, &result, Policy()))
{
return result;
}
// Special cases.
if (x == 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 (x == 0)
{ // No failures are expected if P = 0.
return 0; // Total trials will be just dist.successes.
}
// if (P <= pow(dist.success_fraction(), 1))
if (x <= success_fraction)
{ // p <= pdf(dist, 0) == cdf(dist, 0)
return 0;
}
if (x == 1)
{
return 0;
}
// log(1-x) /log(1-success_fraction) -1; but use log1p in case success_fraction is small
result = boost::math::log1p(-x, Policy()) / boost::math::log1p(-success_fraction, Policy()) - 1;
// Subtract a few epsilons here too?
// to make sure it doesn't slip over, so ceil would be one too many.
return result;
} // RealType quantile(const geometric_distribution dist, p)
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<geometric_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 geometric_distribution<%1%>&, %1%)";
BOOST_MATH_STD_USING
// Error checks:
RealType x = c.param;
const geometric_distribution<RealType, Policy>& dist = c.dist;
RealType success_fraction = dist.success_fraction();
RealType result = 0;
if(false == geometric_detail::check_dist_and_prob(
function,
success_fraction,
x,
&result, Policy()))
{
return result;
}
// Special cases:
if(x == 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 (-x <= boost::math::powm1(dist.success_fraction(), dist.successes(), Policy()))
{ // q <= cdf(complement(dist, 0)) == pdf(dist, 0)
return 0; //
}
if(x == 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
}
// log(x) /log(1-success_fraction) -1; but use log1p in case success_fraction is small
result = log(x) / boost::math::log1p(-success_fraction, Policy()) - 1;
return result;
} // 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_GEOMETRIC_HPP

View File

@@ -0,0 +1,634 @@
// Copyright 2014 Marco Guazzone (marco.guazzone@gmail.com)
//
// 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 module implements the Hyper-Exponential distribution.
//
// References:
// - "Queueing Theory in Manufacturing Systems Analysis and Design" by H.T. Papadopolous, C. Heavey and J. Browne (Chapman & Hall/CRC, 1993)
// - http://reference.wolfram.com/language/ref/HyperexponentialDistribution.html
// - http://en.wikipedia.org/wiki/Hyperexponential_distribution
//
#ifndef BOOST_MATH_DISTRIBUTIONS_HYPEREXPONENTIAL_HPP
#define BOOST_MATH_DISTRIBUTIONS_HYPEREXPONENTIAL_HPP
#include <boost/config.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/exponential.hpp>
#include <boost/math/policies/policy.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/math/tools/roots.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/type_traits/has_pre_increment.hpp>
#include <cstddef>
#include <iterator>
#include <limits>
#include <numeric>
#include <utility>
#include <vector>
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
# include <initializer_list>
#endif
#ifdef _MSC_VER
# pragma warning (push)
# pragma warning(disable:4127) // conditional expression is constant
# pragma warning(disable:4389) // '==' : signed/unsigned mismatch in test_tools
#endif // _MSC_VER
namespace boost { namespace math {
namespace detail {
template <typename Dist>
typename Dist::value_type generic_quantile(const Dist& dist, const typename Dist::value_type& p, const typename Dist::value_type& guess, bool comp, const char* function);
} // Namespace detail
template <typename RealT, typename PolicyT>
class hyperexponential_distribution;
namespace /*<unnamed>*/ { namespace hyperexp_detail {
template <typename T>
void normalize(std::vector<T>& v)
{
if(!v.size())
return; // Our error handlers will get this later
const T sum = std::accumulate(v.begin(), v.end(), static_cast<T>(0));
T final_sum = 0;
const typename std::vector<T>::iterator end = --v.end();
for (typename std::vector<T>::iterator it = v.begin();
it != end;
++it)
{
*it /= sum;
final_sum += *it;
}
*end = 1 - final_sum; // avoids round off errors, ensures the probs really do sum to 1.
}
template <typename RealT, typename PolicyT>
bool check_probabilities(char const* function, std::vector<RealT> const& probabilities, RealT* presult, PolicyT const& pol)
{
BOOST_MATH_STD_USING
const std::size_t n = probabilities.size();
RealT sum = 0;
for (std::size_t i = 0; i < n; ++i)
{
if (probabilities[i] < 0
|| probabilities[i] > 1
|| !(boost::math::isfinite)(probabilities[i]))
{
*presult = policies::raise_domain_error<RealT>(function,
"The elements of parameter \"probabilities\" must be >= 0 and <= 1, but at least one of them was: %1%.",
probabilities[i],
pol);
return false;
}
sum += probabilities[i];
}
//
// We try to keep phase probabilities correctly normalized in the distribution constructors,
// however in practice we have to allow for a very slight divergence from a sum of exactly 1:
//
if (fabs(sum - 1) > tools::epsilon<RealT>() * 2)
{
*presult = policies::raise_domain_error<RealT>(function,
"The elements of parameter \"probabilities\" must sum to 1, but their sum is: %1%.",
sum,
pol);
return false;
}
return true;
}
template <typename RealT, typename PolicyT>
bool check_rates(char const* function, std::vector<RealT> const& rates, RealT* presult, PolicyT const& pol)
{
const std::size_t n = rates.size();
for (std::size_t i = 0; i < n; ++i)
{
if (rates[i] <= 0
|| !(boost::math::isfinite)(rates[i]))
{
*presult = policies::raise_domain_error<RealT>(function,
"The elements of parameter \"rates\" must be > 0, but at least one of them is: %1%.",
rates[i],
pol);
return false;
}
}
return true;
}
template <typename RealT, typename PolicyT>
bool check_dist(char const* function, std::vector<RealT> const& probabilities, std::vector<RealT> const& rates, RealT* presult, PolicyT const& pol)
{
BOOST_MATH_STD_USING
if (probabilities.size() != rates.size())
{
*presult = policies::raise_domain_error<RealT>(function,
"The parameters \"probabilities\" and \"rates\" must have the same length, but their size differ by: %1%.",
fabs(static_cast<RealT>(probabilities.size())-static_cast<RealT>(rates.size())),
pol);
return false;
}
return check_probabilities(function, probabilities, presult, pol)
&& check_rates(function, rates, presult, pol);
}
template <typename RealT, typename PolicyT>
bool check_x(char const* function, RealT x, RealT* presult, PolicyT const& pol)
{
if (x < 0 || (boost::math::isnan)(x))
{
*presult = policies::raise_domain_error<RealT>(function, "The random variable must be >= 0, but is: %1%.", x, pol);
return false;
}
return true;
}
template <typename RealT, typename PolicyT>
bool check_probability(char const* function, RealT p, RealT* presult, PolicyT const& pol)
{
if (p < 0 || p > 1 || (boost::math::isnan)(p))
{
*presult = policies::raise_domain_error<RealT>(function, "The probability be >= 0 and <= 1, but is: %1%.", p, pol);
return false;
}
return true;
}
template <typename RealT, typename PolicyT>
RealT quantile_impl(hyperexponential_distribution<RealT, PolicyT> const& dist, RealT const& p, bool comp)
{
// Don't have a closed form so try to numerically solve the inverse CDF...
typedef typename policies::evaluation<RealT, PolicyT>::type value_type;
typedef typename policies::normalise<PolicyT,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
static const char* function = comp ? "boost::math::quantile(const boost::math::complemented2_type<boost::math::hyperexponential_distribution<%1%>, %1%>&)"
: "boost::math::quantile(const boost::math::hyperexponential_distribution<%1%>&, %1%)";
RealT result = 0;
if (!check_probability(function, p, &result, PolicyT()))
{
return result;
}
const std::size_t n = dist.num_phases();
const std::vector<RealT> probs = dist.probabilities();
const std::vector<RealT> rates = dist.rates();
// A possible (but inaccurate) approximation is given below, where the
// quantile is given by the weighted sum of exponential quantiles:
RealT guess = 0;
if (comp)
{
for (std::size_t i = 0; i < n; ++i)
{
const exponential_distribution<RealT,PolicyT> exp(rates[i]);
guess += probs[i]*quantile(complement(exp, p));
}
}
else
{
for (std::size_t i = 0; i < n; ++i)
{
const exponential_distribution<RealT,PolicyT> exp(rates[i]);
guess += probs[i]*quantile(exp, p);
}
}
// Fast return in case the Hyper-Exponential is essentially an Exponential
if (n == 1)
{
return guess;
}
value_type q;
q = detail::generic_quantile(hyperexponential_distribution<RealT,forwarding_policy>(probs, rates),
p,
guess,
comp,
function);
result = policies::checked_narrowing_cast<RealT,forwarding_policy>(q, function);
return result;
}
}} // Namespace <unnamed>::hyperexp_detail
template <typename RealT = double, typename PolicyT = policies::policy<> >
class hyperexponential_distribution
{
public: typedef RealT value_type;
public: typedef PolicyT policy_type;
public: hyperexponential_distribution()
: probs_(1, 1),
rates_(1, 1)
{
RealT err;
hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
probs_,
rates_,
&err,
PolicyT());
}
// Four arg constructor: no ambiguity here, the arguments must be two pairs of iterators:
public: template <typename ProbIterT, typename RateIterT>
hyperexponential_distribution(ProbIterT prob_first, ProbIterT prob_last,
RateIterT rate_first, RateIterT rate_last)
: probs_(prob_first, prob_last),
rates_(rate_first, rate_last)
{
hyperexp_detail::normalize(probs_);
RealT err;
hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
probs_,
rates_,
&err,
PolicyT());
}
// Two arg constructor from 2 ranges, we SFINAE this out of existance if
// either argument type is incrementable as in that case the type is
// probably an iterator:
public: template <typename ProbRangeT, typename RateRangeT>
hyperexponential_distribution(ProbRangeT const& prob_range,
RateRangeT const& rate_range,
typename boost::disable_if_c<boost::has_pre_increment<ProbRangeT>::value || boost::has_pre_increment<RateRangeT>::value>::type* = 0)
: probs_(boost::begin(prob_range), boost::end(prob_range)),
rates_(boost::begin(rate_range), boost::end(rate_range))
{
hyperexp_detail::normalize(probs_);
RealT err;
hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
probs_,
rates_,
&err,
PolicyT());
}
// Two arg constructor for a pair of iterators: we SFINAE this out of
// existance if neither argument types are incrementable.
// Note that we allow different argument types here to allow for
// construction from an array plus a pointer into that array.
public: template <typename RateIterT, typename RateIterT2>
hyperexponential_distribution(RateIterT const& rate_first,
RateIterT2 const& rate_last,
typename boost::enable_if_c<boost::has_pre_increment<RateIterT>::value || boost::has_pre_increment<RateIterT2>::value>::type* = 0)
: probs_(std::distance(rate_first, rate_last), 1), // will be normalized below
rates_(rate_first, rate_last)
{
hyperexp_detail::normalize(probs_);
RealT err;
hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
probs_,
rates_,
&err,
PolicyT());
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
// Initializer list constructor: allows for construction from array literals:
public: hyperexponential_distribution(std::initializer_list<RealT> l1, std::initializer_list<RealT> l2)
: probs_(l1.begin(), l1.end()),
rates_(l2.begin(), l2.end())
{
hyperexp_detail::normalize(probs_);
RealT err;
hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
probs_,
rates_,
&err,
PolicyT());
}
public: hyperexponential_distribution(std::initializer_list<RealT> l1)
: probs_(l1.size(), 1),
rates_(l1.begin(), l1.end())
{
hyperexp_detail::normalize(probs_);
RealT err;
hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
probs_,
rates_,
&err,
PolicyT());
}
#endif // !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
// Single argument constructor: argument must be a range.
public: template <typename RateRangeT>
hyperexponential_distribution(RateRangeT const& rate_range)
: probs_(boost::size(rate_range), 1), // will be normalized below
rates_(boost::begin(rate_range), boost::end(rate_range))
{
hyperexp_detail::normalize(probs_);
RealT err;
hyperexp_detail::check_dist("boost::math::hyperexponential_distribution<%1%>::hyperexponential_distribution",
probs_,
rates_,
&err,
PolicyT());
}
public: std::vector<RealT> probabilities() const
{
return probs_;
}
public: std::vector<RealT> rates() const
{
return rates_;
}
public: std::size_t num_phases() const
{
return rates_.size();
}
private: std::vector<RealT> probs_;
private: std::vector<RealT> rates_;
}; // class hyperexponential_distribution
// Convenient type synonym for double.
typedef hyperexponential_distribution<double> hyperexponential;
// Range of permissible values for random variable x
template <typename RealT, typename PolicyT>
std::pair<RealT,RealT> range(hyperexponential_distribution<RealT,PolicyT> const&)
{
if (std::numeric_limits<RealT>::has_infinity)
{
return std::make_pair(static_cast<RealT>(0), std::numeric_limits<RealT>::infinity()); // 0 to +inf.
}
return std::make_pair(static_cast<RealT>(0), tools::max_value<RealT>()); // 0 to +<max value>
}
// 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.
template <typename RealT, typename PolicyT>
std::pair<RealT,RealT> support(hyperexponential_distribution<RealT,PolicyT> const&)
{
return std::make_pair(tools::min_value<RealT>(), tools::max_value<RealT>()); // <min value> to +<max value>.
}
template <typename RealT, typename PolicyT>
RealT pdf(hyperexponential_distribution<RealT, PolicyT> const& dist, RealT const& x)
{
BOOST_MATH_STD_USING
RealT result = 0;
if (!hyperexp_detail::check_x("boost::math::pdf(const boost::math::hyperexponential_distribution<%1%>&, %1%)", x, &result, PolicyT()))
{
return result;
}
const std::size_t n = dist.num_phases();
const std::vector<RealT> probs = dist.probabilities();
const std::vector<RealT> rates = dist.rates();
for (std::size_t i = 0; i < n; ++i)
{
const exponential_distribution<RealT,PolicyT> exp(rates[i]);
result += probs[i]*pdf(exp, x);
//result += probs[i]*rates[i]*exp(-rates[i]*x);
}
return result;
}
template <typename RealT, typename PolicyT>
RealT cdf(hyperexponential_distribution<RealT, PolicyT> const& dist, RealT const& x)
{
RealT result = 0;
if (!hyperexp_detail::check_x("boost::math::cdf(const boost::math::hyperexponential_distribution<%1%>&, %1%)", x, &result, PolicyT()))
{
return result;
}
const std::size_t n = dist.num_phases();
const std::vector<RealT> probs = dist.probabilities();
const std::vector<RealT> rates = dist.rates();
for (std::size_t i = 0; i < n; ++i)
{
const exponential_distribution<RealT,PolicyT> exp(rates[i]);
result += probs[i]*cdf(exp, x);
}
return result;
}
template <typename RealT, typename PolicyT>
RealT quantile(hyperexponential_distribution<RealT, PolicyT> const& dist, RealT const& p)
{
return hyperexp_detail::quantile_impl(dist, p , false);
}
template <typename RealT, typename PolicyT>
RealT cdf(complemented2_type<hyperexponential_distribution<RealT,PolicyT>, RealT> const& c)
{
RealT const& x = c.param;
hyperexponential_distribution<RealT,PolicyT> const& dist = c.dist;
RealT result = 0;
if (!hyperexp_detail::check_x("boost::math::cdf(boost::math::complemented2_type<const boost::math::hyperexponential_distribution<%1%>&, %1%>)", x, &result, PolicyT()))
{
return result;
}
const std::size_t n = dist.num_phases();
const std::vector<RealT> probs = dist.probabilities();
const std::vector<RealT> rates = dist.rates();
for (std::size_t i = 0; i < n; ++i)
{
const exponential_distribution<RealT,PolicyT> exp(rates[i]);
result += probs[i]*cdf(complement(exp, x));
}
return result;
}
template <typename RealT, typename PolicyT>
RealT quantile(complemented2_type<hyperexponential_distribution<RealT, PolicyT>, RealT> const& c)
{
RealT const& p = c.param;
hyperexponential_distribution<RealT,PolicyT> const& dist = c.dist;
return hyperexp_detail::quantile_impl(dist, p , true);
}
template <typename RealT, typename PolicyT>
RealT mean(hyperexponential_distribution<RealT, PolicyT> const& dist)
{
RealT result = 0;
const std::size_t n = dist.num_phases();
const std::vector<RealT> probs = dist.probabilities();
const std::vector<RealT> rates = dist.rates();
for (std::size_t i = 0; i < n; ++i)
{
const exponential_distribution<RealT,PolicyT> exp(rates[i]);
result += probs[i]*mean(exp);
}
return result;
}
template <typename RealT, typename PolicyT>
RealT variance(hyperexponential_distribution<RealT, PolicyT> const& dist)
{
RealT result = 0;
const std::size_t n = dist.num_phases();
const std::vector<RealT> probs = dist.probabilities();
const std::vector<RealT> rates = dist.rates();
for (std::size_t i = 0; i < n; ++i)
{
result += probs[i]/(rates[i]*rates[i]);
}
const RealT mean = boost::math::mean(dist);
result = 2*result-mean*mean;
return result;
}
template <typename RealT, typename PolicyT>
RealT skewness(hyperexponential_distribution<RealT,PolicyT> const& dist)
{
BOOST_MATH_STD_USING
const std::size_t n = dist.num_phases();
const std::vector<RealT> probs = dist.probabilities();
const std::vector<RealT> rates = dist.rates();
RealT s1 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i}
RealT s2 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i^2}
RealT s3 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i^3}
for (std::size_t i = 0; i < n; ++i)
{
const RealT p = probs[i];
const RealT r = rates[i];
const RealT r2 = r*r;
const RealT r3 = r2*r;
s1 += p/r;
s2 += p/r2;
s3 += p/r3;
}
const RealT s1s1 = s1*s1;
const RealT num = (6*s3 - (3*(2*s2 - s1s1) + s1s1)*s1);
const RealT den = (2*s2 - s1s1);
return num / pow(den, static_cast<RealT>(1.5));
}
template <typename RealT, typename PolicyT>
RealT kurtosis(hyperexponential_distribution<RealT,PolicyT> const& dist)
{
const std::size_t n = dist.num_phases();
const std::vector<RealT> probs = dist.probabilities();
const std::vector<RealT> rates = dist.rates();
RealT s1 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i}
RealT s2 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i^2}
RealT s3 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i^3}
RealT s4 = 0; // \sum_{i=1}^n \frac{p_i}{\lambda_i^4}
for (std::size_t i = 0; i < n; ++i)
{
const RealT p = probs[i];
const RealT r = rates[i];
const RealT r2 = r*r;
const RealT r3 = r2*r;
const RealT r4 = r3*r;
s1 += p/r;
s2 += p/r2;
s3 += p/r3;
s4 += p/r4;
}
const RealT s1s1 = s1*s1;
const RealT num = (24*s4 - 24*s3*s1 + 3*(2*(2*s2 - s1s1) + s1s1)*s1s1);
const RealT den = (2*s2 - s1s1);
return num/(den*den);
}
template <typename RealT, typename PolicyT>
RealT kurtosis_excess(hyperexponential_distribution<RealT,PolicyT> const& dist)
{
return kurtosis(dist) - 3;
}
template <typename RealT, typename PolicyT>
RealT mode(hyperexponential_distribution<RealT,PolicyT> const& /*dist*/)
{
return 0;
}
}} // namespace boost::math
#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>
#include <boost/math/distributions/detail/generic_quantile.hpp>
#endif // BOOST_MATH_DISTRIBUTIONS_HYPEREXPONENTIAL

View File

@@ -0,0 +1,293 @@
// Copyright 2008 Gautam Sewani
// Copyright 2008 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_DISTRIBUTIONS_HYPERGEOMETRIC_HPP
#define BOOST_MATH_DISTRIBUTIONS_HYPERGEOMETRIC_HPP
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/detail/hypergeometric_pdf.hpp>
#include <boost/math/distributions/detail/hypergeometric_cdf.hpp>
#include <boost/math/distributions/detail/hypergeometric_quantile.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
namespace boost { namespace math {
template <class RealType = double, class Policy = policies::policy<> >
class hypergeometric_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
hypergeometric_distribution(unsigned r, unsigned n, unsigned N) // Constructor.
: m_n(n), m_N(N), m_r(r)
{
static const char* function = "boost::math::hypergeometric_distribution<%1%>::hypergeometric_distribution";
RealType ret;
check_params(function, &ret);
}
// Accessor functions.
unsigned total()const
{
return m_N;
}
unsigned defective()const
{
return m_r;
}
unsigned sample_count()const
{
return m_n;
}
bool check_params(const char* function, RealType* result)const
{
if(m_r > m_N)
{
*result = boost::math::policies::raise_domain_error<RealType>(
function, "Parameter r out of range: must be <= N but got %1%", static_cast<RealType>(m_r), Policy());
return false;
}
if(m_n > m_N)
{
*result = boost::math::policies::raise_domain_error<RealType>(
function, "Parameter n out of range: must be <= N but got %1%", static_cast<RealType>(m_n), Policy());
return false;
}
return true;
}
bool check_x(unsigned x, const char* function, RealType* result)const
{
if(x < static_cast<unsigned>((std::max)(0, (int)(m_n + m_r) - (int)(m_N))))
{
*result = boost::math::policies::raise_domain_error<RealType>(
function, "Random variable out of range: must be > 0 and > m + r - N but got %1%", static_cast<RealType>(x), Policy());
return false;
}
if(x > (std::min)(m_r, m_n))
{
*result = boost::math::policies::raise_domain_error<RealType>(
function, "Random variable out of range: must be less than both n and r but got %1%", static_cast<RealType>(x), Policy());
return false;
}
return true;
}
private:
// Data members:
unsigned m_n; // number of items picked
unsigned m_N; // number of "total" items
unsigned m_r; // number of "defective" items
}; // class hypergeometric_distribution
typedef hypergeometric_distribution<double> hypergeometric;
template <class RealType, class Policy>
inline const std::pair<unsigned, unsigned> range(const hypergeometric_distribution<RealType, Policy>& dist)
{ // Range of permissible values for random variable x.
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:4267)
#endif
unsigned r = dist.defective();
unsigned n = dist.sample_count();
unsigned N = dist.total();
unsigned l = static_cast<unsigned>((std::max)(0, (int)(n + r) - (int)(N)));
unsigned u = (std::min)(r, n);
return std::pair<unsigned, unsigned>(l, u);
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
}
template <class RealType, class Policy>
inline const std::pair<unsigned, unsigned> support(const hypergeometric_distribution<RealType, Policy>& d)
{
return range(d);
}
template <class RealType, class Policy>
inline RealType pdf(const hypergeometric_distribution<RealType, Policy>& dist, const unsigned& x)
{
static const char* function = "boost::math::pdf(const hypergeometric_distribution<%1%>&, const %1%&)";
RealType result = 0;
if(!dist.check_params(function, &result))
return result;
if(!dist.check_x(x, function, &result))
return result;
return boost::math::detail::hypergeometric_pdf<RealType>(
x, dist.defective(), dist.sample_count(), dist.total(), Policy());
}
template <class RealType, class Policy, class U>
inline RealType pdf(const hypergeometric_distribution<RealType, Policy>& dist, const U& x)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::pdf(const hypergeometric_distribution<%1%>&, const %1%&)";
RealType r = static_cast<RealType>(x);
unsigned u = itrunc(r, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type());
if(u != r)
{
return boost::math::policies::raise_domain_error<RealType>(
function, "Random variable out of range: must be an integer but got %1%", r, Policy());
}
return pdf(dist, u);
}
template <class RealType, class Policy>
inline RealType cdf(const hypergeometric_distribution<RealType, Policy>& dist, const unsigned& x)
{
static const char* function = "boost::math::cdf(const hypergeometric_distribution<%1%>&, const %1%&)";
RealType result = 0;
if(!dist.check_params(function, &result))
return result;
if(!dist.check_x(x, function, &result))
return result;
return boost::math::detail::hypergeometric_cdf<RealType>(
x, dist.defective(), dist.sample_count(), dist.total(), false, Policy());
}
template <class RealType, class Policy, class U>
inline RealType cdf(const hypergeometric_distribution<RealType, Policy>& dist, const U& x)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::cdf(const hypergeometric_distribution<%1%>&, const %1%&)";
RealType r = static_cast<RealType>(x);
unsigned u = itrunc(r, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type());
if(u != r)
{
return boost::math::policies::raise_domain_error<RealType>(
function, "Random variable out of range: must be an integer but got %1%", r, Policy());
}
return cdf(dist, u);
}
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<hypergeometric_distribution<RealType, Policy>, unsigned>& c)
{
static const char* function = "boost::math::cdf(const hypergeometric_distribution<%1%>&, const %1%&)";
RealType result = 0;
if(!c.dist.check_params(function, &result))
return result;
if(!c.dist.check_x(c.param, function, &result))
return result;
return boost::math::detail::hypergeometric_cdf<RealType>(
c.param, c.dist.defective(), c.dist.sample_count(), c.dist.total(), true, Policy());
}
template <class RealType, class Policy, class U>
inline RealType cdf(const complemented2_type<hypergeometric_distribution<RealType, Policy>, U>& c)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::cdf(const hypergeometric_distribution<%1%>&, const %1%&)";
RealType r = static_cast<RealType>(c.param);
unsigned u = itrunc(r, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type());
if(u != r)
{
return boost::math::policies::raise_domain_error<RealType>(
function, "Random variable out of range: must be an integer but got %1%", r, Policy());
}
return cdf(complement(c.dist, u));
}
template <class RealType, class Policy>
inline RealType quantile(const hypergeometric_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions
// Checking function argument
RealType result = 0;
const char* function = "boost::math::quantile(const hypergeometric_distribution<%1%>&, %1%)";
if (false == dist.check_params(function, &result)) return result;
if(false == detail::check_probability(function, p, &result, Policy())) return result;
return static_cast<RealType>(detail::hypergeometric_quantile(p, RealType(1 - p), dist.defective(), dist.sample_count(), dist.total(), Policy()));
} // quantile
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<hypergeometric_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
// Checking function argument
RealType result = 0;
const char* function = "quantile(const complemented2_type<hypergeometric_distribution<%1%>, %1%>&)";
if (false == c.dist.check_params(function, &result)) return result;
if(false == detail::check_probability(function, c.param, &result, Policy())) return result;
return static_cast<RealType>(detail::hypergeometric_quantile(RealType(1 - c.param), c.param, c.dist.defective(), c.dist.sample_count(), c.dist.total(), Policy()));
} // quantile
template <class RealType, class Policy>
inline RealType mean(const hypergeometric_distribution<RealType, Policy>& dist)
{
return static_cast<RealType>(dist.defective() * dist.sample_count()) / dist.total();
} // RealType mean(const hypergeometric_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType variance(const hypergeometric_distribution<RealType, Policy>& dist)
{
RealType r = static_cast<RealType>(dist.defective());
RealType n = static_cast<RealType>(dist.sample_count());
RealType N = static_cast<RealType>(dist.total());
return n * r * (N - r) * (N - n) / (N * N * (N - 1));
} // RealType variance(const hypergeometric_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType mode(const hypergeometric_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING
RealType r = static_cast<RealType>(dist.defective());
RealType n = static_cast<RealType>(dist.sample_count());
RealType N = static_cast<RealType>(dist.total());
return floor((r + 1) * (n + 1) / (N + 2));
}
template <class RealType, class Policy>
inline RealType skewness(const hypergeometric_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING
RealType r = static_cast<RealType>(dist.defective());
RealType n = static_cast<RealType>(dist.sample_count());
RealType N = static_cast<RealType>(dist.total());
return (N - 2 * r) * sqrt(N - 1) * (N - 2 * n) / (sqrt(n * r * (N - r) * (N - n)) * (N - 2));
} // RealType skewness(const hypergeometric_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType kurtosis_excess(const hypergeometric_distribution<RealType, Policy>& dist)
{
RealType r = static_cast<RealType>(dist.defective());
RealType n = static_cast<RealType>(dist.sample_count());
RealType N = static_cast<RealType>(dist.total());
RealType t1 = N * N * (N - 1) / (r * (N - 2) * (N - 3) * (N - r));
RealType t2 = (N * (N + 1) - 6 * N * (N - r)) / (n * (N - n))
+ 3 * r * (N - r) * (N + 6) / (N * N) - 6;
return t1 * t2;
} // RealType kurtosis_excess(const hypergeometric_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType kurtosis(const hypergeometric_distribution<RealType, Policy>& dist)
{
return kurtosis_excess(dist) + 3;
} // RealType kurtosis_excess(const hypergeometric_distribution<RealType, Policy>& dist)
}} // namespaces
// 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 // include guard

View File

@@ -0,0 +1,391 @@
// Copyright John Maddock 2010.
// Copyright Paul A. Bristow 2010.
// 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_INVERSE_CHI_SQUARED_HPP
#define BOOST_MATH_DISTRIBUTIONS_INVERSE_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> // for complements.
#include <boost/math/distributions/detail/common_error_handling.hpp> // for error checks.
#include <boost/math/special_functions/fpclassify.hpp> // for isfinite
// See http://en.wikipedia.org/wiki/Scaled-inverse-chi-square_distribution
// for definitions of this scaled version.
// See http://en.wikipedia.org/wiki/Inverse-chi-square_distribution
// for unscaled version.
// http://reference.wolfram.com/mathematica/ref/InverseChiSquareDistribution.html
// Weisstein, Eric W. "Inverse Chi-Squared Distribution." From MathWorld--A Wolfram Web Resource.
// http://mathworld.wolfram.com/InverseChi-SquaredDistribution.html
#include <utility>
namespace boost{ namespace math{
namespace detail
{
template <class RealType, class Policy>
inline bool check_inverse_chi_squared( // Check both distribution parameters.
const char* function,
RealType degrees_of_freedom, // degrees_of_freedom (aka nu).
RealType scale, // scale (aka sigma^2)
RealType* result,
const Policy& pol)
{
return check_scale(function, scale, result, pol)
&& check_df(function, degrees_of_freedom,
result, pol);
} // bool check_inverse_chi_squared
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class inverse_chi_squared_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
inverse_chi_squared_distribution(RealType df, RealType l_scale) : m_df(df), m_scale (l_scale)
{
RealType result;
detail::check_df(
"boost::math::inverse_chi_squared_distribution<%1%>::inverse_chi_squared_distribution",
m_df, &result, Policy())
&& detail::check_scale(
"boost::math::inverse_chi_squared_distribution<%1%>::inverse_chi_squared_distribution",
m_scale, &result, Policy());
} // inverse_chi_squared_distribution constructor
inverse_chi_squared_distribution(RealType df = 1) : m_df(df)
{
RealType result;
m_scale = 1 / m_df ; // Default scale = 1 / degrees of freedom (Wikipedia definition 1).
detail::check_df(
"boost::math::inverse_chi_squared_distribution<%1%>::inverse_chi_squared_distribution",
m_df, &result, Policy());
} // inverse_chi_squared_distribution
RealType degrees_of_freedom()const
{
return m_df; // aka nu
}
RealType scale()const
{
return m_scale; // aka xi
}
// Parameter estimation: NOT implemented yet.
//static RealType find_degrees_of_freedom(
// RealType difference_from_variance,
// RealType alpha,
// RealType beta,
// RealType variance,
// RealType hint = 100);
private:
// Data members:
RealType m_df; // degrees of freedom are treated as a real number.
RealType m_scale; // distribution scale.
}; // class chi_squared_distribution
typedef inverse_chi_squared_distribution<double> inverse_chi_squared;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const inverse_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>(static_cast<RealType>(0), max_value<RealType>()); // 0 to + infinity.
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const inverse_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>(static_cast<RealType>(0), tools::max_value<RealType>()); // 0 to + infinity.
}
template <class RealType, class Policy>
RealType pdf(const inverse_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions.
RealType df = dist.degrees_of_freedom();
RealType scale = dist.scale();
RealType error_result;
static const char* function = "boost::math::pdf(const inverse_chi_squared_distribution<%1%>&, %1%)";
if(false == detail::check_inverse_chi_squared
(function, df, scale, &error_result, Policy())
)
{ // Bad distribution.
return error_result;
}
if((x < 0) || !(boost::math::isfinite)(x))
{ // Bad x.
return policies::raise_domain_error<RealType>(
function, "inverse Chi Square parameter was %1%, but must be >= 0 !", x, Policy());
}
if(x == 0)
{ // Treat as special case.
return 0;
}
// Wikipedia scaled inverse chi sq (df, scale) related to inv gamma (df/2, df * scale /2)
// so use inverse gamma pdf with shape = df/2, scale df * scale /2
// RealType shape = df /2; // inv_gamma shape
// RealType scale = df * scale/2; // inv_gamma scale
// RealType result = gamma_p_derivative(shape, scale / x, Policy()) * scale / (x * x);
RealType result = df * scale/2 / x;
if(result < tools::min_value<RealType>())
return 0; // Random variable is near enough infinite.
result = gamma_p_derivative(df/2, result, Policy()) * df * scale/2;
if(result != 0) // prevent 0 / 0, gamma_p_derivative -> 0 faster than x^2
result /= (x * x);
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const inverse_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
{
static const char* function = "boost::math::cdf(const inverse_chi_squared_distribution<%1%>&, %1%)";
RealType df = dist.degrees_of_freedom();
RealType scale = dist.scale();
RealType error_result;
if(false ==
detail::check_inverse_chi_squared(function, df, scale, &error_result, Policy())
)
{ // Bad distribution.
return error_result;
}
if((x < 0) || !(boost::math::isfinite)(x))
{ // Bad x.
return policies::raise_domain_error<RealType>(
function, "inverse Chi Square parameter was %1%, but must be >= 0 !", x, Policy());
}
if (x == 0)
{ // Treat zero as a special case.
return 0;
}
// RealType shape = df /2; // inv_gamma shape,
// RealType scale = df * scale/2; // inv_gamma scale,
// result = boost::math::gamma_q(shape, scale / x, Policy()); // inverse_gamma code.
return boost::math::gamma_q(df / 2, (df * (scale / 2)) / x, Policy());
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const inverse_chi_squared_distribution<RealType, Policy>& dist, const RealType& p)
{
using boost::math::gamma_q_inv;
RealType df = dist.degrees_of_freedom();
RealType scale = dist.scale();
static const char* function = "boost::math::quantile(const inverse_chi_squared_distribution<%1%>&, %1%)";
// Error check:
RealType error_result;
if(false == detail::check_df(
function, df, &error_result, Policy())
&& detail::check_probability(
function, p, &error_result, Policy()))
{
return error_result;
}
if(false == detail::check_probability(
function, p, &error_result, Policy()))
{
return error_result;
}
// RealType shape = df /2; // inv_gamma shape,
// RealType scale = df * scale/2; // inv_gamma scale,
// result = scale / gamma_q_inv(shape, p, Policy());
RealType result = gamma_q_inv(df /2, p, Policy());
if(result == 0)
return policies::raise_overflow_error<RealType, Policy>(function, "Random variable is infinite.", Policy());
result = df * (scale / 2) / result;
return result;
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<inverse_chi_squared_distribution<RealType, Policy>, RealType>& c)
{
using boost::math::gamma_q_inv;
RealType const& df = c.dist.degrees_of_freedom();
RealType const& scale = c.dist.scale();
RealType const& x = c.param;
static const char* function = "boost::math::cdf(const inverse_chi_squared_distribution<%1%>&, %1%)";
// Error check:
RealType error_result;
if(false == detail::check_df(
function, df, &error_result, Policy()))
{
return error_result;
}
if (x == 0)
{ // Treat zero as a special case.
return 1;
}
if((x < 0) || !(boost::math::isfinite)(x))
{
return policies::raise_domain_error<RealType>(
function, "inverse Chi Square parameter was %1%, but must be > 0 !", x, Policy());
}
// RealType shape = df /2; // inv_gamma shape,
// RealType scale = df * scale/2; // inv_gamma scale,
// result = gamma_p(shape, scale/c.param, Policy()); use inv_gamma.
return gamma_p(df / 2, (df * scale/2) / x, Policy()); // OK
} // cdf(complemented
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<inverse_chi_squared_distribution<RealType, Policy>, RealType>& c)
{
using boost::math::gamma_q_inv;
RealType const& df = c.dist.degrees_of_freedom();
RealType const& scale = c.dist.scale();
RealType const& q = c.param;
static const char* function = "boost::math::quantile(const inverse_chi_squared_distribution<%1%>&, %1%)";
// Error check:
RealType error_result;
if(false == detail::check_df(function, df, &error_result, Policy()))
{
return error_result;
}
if(false == detail::check_probability(function, q, &error_result, Policy()))
{
return error_result;
}
// RealType shape = df /2; // inv_gamma shape,
// RealType scale = df * scale/2; // inv_gamma scale,
// result = scale / gamma_p_inv(shape, q, Policy()); // using inv_gamma.
RealType result = gamma_p_inv(df/2, q, Policy());
if(result == 0)
return policies::raise_overflow_error<RealType, Policy>(function, "Random variable is infinite.", Policy());
result = (df * scale / 2) / result;
return result;
} // quantile(const complement
template <class RealType, class Policy>
inline RealType mean(const inverse_chi_squared_distribution<RealType, Policy>& dist)
{ // Mean of inverse Chi-Squared distribution.
RealType df = dist.degrees_of_freedom();
RealType scale = dist.scale();
static const char* function = "boost::math::mean(const inverse_chi_squared_distribution<%1%>&)";
if(df <= 2)
return policies::raise_domain_error<RealType>(
function,
"inverse Chi-Squared distribution only has a mode for degrees of freedom > 2, but got degrees of freedom = %1%.",
df, Policy());
return (df * scale) / (df - 2);
} // mean
template <class RealType, class Policy>
inline RealType variance(const inverse_chi_squared_distribution<RealType, Policy>& dist)
{ // Variance of inverse Chi-Squared distribution.
RealType df = dist.degrees_of_freedom();
RealType scale = dist.scale();
static const char* function = "boost::math::variance(const inverse_chi_squared_distribution<%1%>&)";
if(df <= 4)
{
return policies::raise_domain_error<RealType>(
function,
"inverse Chi-Squared distribution only has a variance for degrees of freedom > 4, but got degrees of freedom = %1%.",
df, Policy());
}
return 2 * df * df * scale * scale / ((df - 2)*(df - 2) * (df - 4));
} // variance
template <class RealType, class Policy>
inline RealType mode(const inverse_chi_squared_distribution<RealType, Policy>& dist)
{ // mode is not defined in Mathematica.
// See Discussion section http://en.wikipedia.org/wiki/Talk:Scaled-inverse-chi-square_distribution
// for origin of the formula used below.
RealType df = dist.degrees_of_freedom();
RealType scale = dist.scale();
static const char* function = "boost::math::mode(const inverse_chi_squared_distribution<%1%>&)";
if(df < 0)
return policies::raise_domain_error<RealType>(
function,
"inverse Chi-Squared distribution only has a mode for degrees of freedom >= 0, but got degrees of freedom = %1%.",
df, Policy());
return (df * scale) / (df + 2);
}
//template <class RealType, class Policy>
//inline RealType median(const inverse_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 inverse_Chi-Squared distribution only has a median for degrees of freedom >= 0, but got degrees of freedom = %1%.",
// df);
// return df;
//}
// Now implemented via quantile(half) in derived accessors.
template <class RealType, class Policy>
inline RealType skewness(const inverse_chi_squared_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // For ADL
RealType df = dist.degrees_of_freedom();
static const char* function = "boost::math::skewness(const inverse_chi_squared_distribution<%1%>&)";
if(df <= 6)
return policies::raise_domain_error<RealType>(
function,
"inverse Chi-Squared distribution only has a skewness for degrees of freedom > 6, but got degrees of freedom = %1%.",
df, Policy());
return 4 * sqrt (2 * (df - 4)) / (df - 6); // Not a function of scale.
}
template <class RealType, class Policy>
inline RealType kurtosis(const inverse_chi_squared_distribution<RealType, Policy>& dist)
{
RealType df = dist.degrees_of_freedom();
static const char* function = "boost::math::kurtosis(const inverse_chi_squared_distribution<%1%>&)";
if(df <= 8)
return policies::raise_domain_error<RealType>(
function,
"inverse Chi-Squared distribution only has a kurtosis for degrees of freedom > 8, but got degrees of freedom = %1%.",
df, Policy());
return kurtosis_excess(dist) + 3;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const inverse_chi_squared_distribution<RealType, Policy>& dist)
{
RealType df = dist.degrees_of_freedom();
static const char* function = "boost::math::kurtosis(const inverse_chi_squared_distribution<%1%>&)";
if(df <= 8)
return policies::raise_domain_error<RealType>(
function,
"inverse Chi-Squared distribution only has a kurtosis excess for degrees of freedom > 8, but got degrees of freedom = %1%.",
df, Policy());
return 12 * (5 * df - 22) / ((df - 6 )*(df - 8)); // Not a function of scale.
}
//
// Parameter estimation comes last:
//
} // 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_INVERSE_CHI_SQUARED_HPP

View File

@@ -0,0 +1,461 @@
// inverse_gamma.hpp
// Copyright Paul A. Bristow 2010.
// Copyright John Maddock 2010.
// 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_INVERSE_GAMMA_HPP
#define BOOST_STATS_INVERSE_GAMMA_HPP
// Inverse Gamma Distribution is a two-parameter family
// of continuous probability distributions
// on the positive real line, which is the distribution of
// the reciprocal of a variable distributed according to the gamma distribution.
// http://en.wikipedia.org/wiki/Inverse-gamma_distribution
// http://rss.acs.unt.edu/Rdoc/library/pscl/html/igamma.html
// See also gamma distribution at 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_inverse_gamma_shape(
const char* function, // inverse_gamma
RealType shape, // shape aka alpha
RealType* result, // to update, perhaps with NaN
const Policy& pol)
{ // Sources say shape argument must be > 0
// but seems logical to allow shape zero as special case,
// returning pdf and cdf zero (but not < 0).
// (Functions like mean, variance with other limits on shape are checked
// in version including an operator & limit below).
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;
} //bool check_inverse_gamma_shape
template <class RealType, class Policy>
inline bool check_inverse_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_inverse_gamma(
const char* function, // TODO swap these over, so shape is first.
RealType scale, // scale aka beta
RealType shape, // shape aka alpha
RealType* result, const Policy& pol)
{
return check_scale(function, scale, result, pol)
&& check_inverse_gamma_shape(function, shape, result, pol);
} // bool check_inverse_gamma
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class inverse_gamma_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
inverse_gamma_distribution(RealType l_shape = 1, RealType l_scale = 1)
: m_shape(l_shape), m_scale(l_scale)
{
RealType result;
detail::check_inverse_gamma(
"boost::math::inverse_gamma_distribution<%1%>::inverse_gamma_distribution",
l_scale, l_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 inverse_gamma_distribution<double> inverse_gamma;
// typedef - but potential clash with name of inverse gamma *function*.
// but there is a typedef for gamma
// typedef boost::math::gamma_distribution<Type, Policy> gamma;
// Allow random variable x to be zero, treated as a special case (unlike some definitions).
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const inverse_gamma_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 inverse_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;
using boost::math::tools::min_value;
return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
}
template <class RealType, class Policy>
inline RealType pdf(const inverse_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 inverse_gamma_distribution<%1%>&, %1%)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result = 0;
if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
{ // distribution parameters bad.
return result;
}
if(x == 0)
{ // Treat random variate zero as a special case.
return 0;
}
else if(false == detail::check_inverse_gamma_x(function, x, &result, Policy()))
{ // x bad.
return result;
}
result = scale / x;
if(result < tools::min_value<RealType>())
return 0; // random variable is infinite or so close as to make no difference.
result = gamma_p_derivative(shape, result, Policy()) * scale;
if(0 != result)
{
if(x < 0)
{
// x * x may under or overflow, likewise our result,
// so be extra careful about the arithmetic:
RealType lim = tools::max_value<RealType>() * x;
if(lim < result)
return policies::raise_overflow_error<RealType, Policy>(function, "PDF is infinite.", Policy());
result /= x;
if(lim < result)
return policies::raise_overflow_error<RealType, Policy>(function, "PDF is infinite.", Policy());
result /= x;
}
result /= (x * x);
}
// better than naive
// result = (pow(scale, shape) * pow(x, (-shape -1)) * exp(-scale/x) ) / tgamma(shape);
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const inverse_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 inverse_gamma_distribution<%1%>&, %1%)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result = 0;
if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
{ // distribution parameters bad.
return result;
}
if (x == 0)
{ // Treat zero as a special case.
return 0;
}
else if(false == detail::check_inverse_gamma_x(function, x, &result, Policy()))
{ // x bad
return result;
}
result = boost::math::gamma_q(shape, scale / x, Policy());
// result = tgamma(shape, scale / x) / tgamma(shape); // naive using tgamma
return result;
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const inverse_gamma_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions
using boost::math::gamma_q_inv;
static const char* function = "boost::math::quantile(const inverse_gamma_distribution<%1%>&, %1%)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result = 0;
if(false == detail::check_inverse_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_q_inv(shape, p, Policy());
if((result < 1) && (result * tools::max_value<RealType>() < scale))
return policies::raise_overflow_error<RealType, Policy>(function, "Value of random variable in inverse gamma distribution quantile is infinite.", Policy());
result = scale / result;
return result;
}
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<inverse_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 = 0;
if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
return result;
if(false == detail::check_inverse_gamma_x(function, c.param, &result, Policy()))
return result;
if(c.param == 0)
return 1; // Avoid division by zero
//result = 1. - gamma_q(shape, c.param / scale, Policy());
result = gamma_p(shape, scale/c.param, Policy());
return result;
}
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<inverse_gamma_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::quantile(const inverse_gamma_distribution<%1%>&, %1%)";
RealType shape = c.dist.shape();
RealType scale = c.dist.scale();
RealType q = c.param;
RealType result = 0;
if(false == detail::check_inverse_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_p_inv(shape, q, Policy());
if((result < 1) && (result * tools::max_value<RealType>() < scale))
return policies::raise_overflow_error<RealType, Policy>(function, "Value of random variable in inverse gamma distribution quantile is infinite.", Policy());
result = scale / result;
return result;
}
template <class RealType, class Policy>
inline RealType mean(const inverse_gamma_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::mean(const inverse_gamma_distribution<%1%>&)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if((shape <= 1) || !(boost::math::isfinite)(shape))
{
result = policies::raise_domain_error<RealType>(
function,
"Shape parameter is %1%, but for a defined mean it must be > 1", shape, Policy());
return result;
}
result = scale / (shape - 1);
return result;
} // mean
template <class RealType, class Policy>
inline RealType variance(const inverse_gamma_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::variance(const inverse_gamma_distribution<%1%>&)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if((shape <= 2) || !(boost::math::isfinite)(shape))
{
result = policies::raise_domain_error<RealType>(
function,
"Shape parameter is %1%, but for a defined variance it must be > 2", shape, Policy());
return result;
}
result = (scale * scale) / ((shape - 1) * (shape -1) * (shape -2));
return result;
}
template <class RealType, class Policy>
inline RealType mode(const inverse_gamma_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::mode(const inverse_gamma_distribution<%1%>&)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result = 0;
if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
{
return result;
}
// Only defined for shape >= 0, but is checked by check_inverse_gamma.
result = scale / (shape + 1);
return result;
}
//template <class RealType, class Policy>
//inline RealType median(const gamma_distribution<RealType, Policy>& dist)
//{ // Wikipedia does not define median,
// so rely on default definition quantile(0.5) in derived accessors.
// return result.
//}
template <class RealType, class Policy>
inline RealType skewness(const inverse_gamma_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::skewness(const inverse_gamma_distribution<%1%>&)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if((shape <= 3) || !(boost::math::isfinite)(shape))
{
result = policies::raise_domain_error<RealType>(
function,
"Shape parameter is %1%, but for a defined skewness it must be > 3", shape, Policy());
return result;
}
result = (4 * sqrt(shape - 2) ) / (shape - 3);
return result;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const inverse_gamma_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
static const char* function = "boost::math::kurtosis_excess(const inverse_gamma_distribution<%1%>&)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if((shape <= 4) || !(boost::math::isfinite)(shape))
{
result = policies::raise_domain_error<RealType>(
function,
"Shape parameter is %1%, but for a defined kurtosis excess it must be > 4", shape, Policy());
return result;
}
result = (30 * shape - 66) / ((shape - 3) * (shape - 4));
return result;
}
template <class RealType, class Policy>
inline RealType kurtosis(const inverse_gamma_distribution<RealType, Policy>& dist)
{
static const char* function = "boost::math::kurtosis(const inverse_gamma_distribution<%1%>&)";
RealType shape = dist.shape();
RealType scale = dist.scale();
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if((shape <= 4) || !(boost::math::isfinite)(shape))
{
result = policies::raise_domain_error<RealType>(
function,
"Shape parameter is %1%, but for a defined kurtosis it must be > 4", shape, Policy());
return result;
}
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_INVERSE_GAMMA_HPP

View File

@@ -0,0 +1,527 @@
// Copyright John Maddock 2010.
// Copyright Paul A. Bristow 2010.
// 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_INVERSE_GAUSSIAN_HPP
#define BOOST_STATS_INVERSE_GAUSSIAN_HPP
#ifdef _MSC_VER
#pragma warning(disable: 4512) // assignment operator could not be generated
#endif
// http://en.wikipedia.org/wiki/Normal-inverse_Gaussian_distribution
// http://mathworld.wolfram.com/InverseGaussianDistribution.html
// The normal-inverse Gaussian distribution
// also called the Wald distribution (some sources limit this to when mean = 1).
// It is the continuous probability distribution
// that is defined as the normal variance-mean mixture where the mixing density is the
// inverse Gaussian distribution. The tails of the distribution decrease more slowly
// than the normal distribution. It is therefore suitable to model phenomena
// where numerically large values are more probable than is the case for the normal distribution.
// The Inverse Gaussian distribution was first studied in relationship to Brownian motion.
// In 1956 M.C.K. Tweedie used the name 'Inverse Gaussian' because there is an inverse
// relationship between the time to cover a unit distance and distance covered in unit time.
// Examples are returns from financial assets and turbulent wind speeds.
// The normal-inverse Gaussian distributions form
// a subclass of the generalised hyperbolic distributions.
// See also
// 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
// http://www.jstatsoft.org/v26/i04/paper General class of inverse Gaussian distributions.
// ig package - withdrawn but at http://cran.r-project.org/src/contrib/Archive/ig/
// http://www.stat.ucl.ac.be/ISdidactique/Rhelp/library/SuppDists/html/inverse_gaussian.html
// R package for dinverse_gaussian, ...
// http://www.statsci.org/s/inverse_gaussian.s and http://www.statsci.org/s/inverse_gaussian.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 <boost/math/distributions/normal.hpp>
#include <boost/math/distributions/gamma.hpp> // for gamma function
// using boost::math::gamma_p;
#include <boost/math/tools/tuple.hpp>
//using std::tr1::tuple;
//using std::tr1::make_tuple;
#include <boost/math/tools/roots.hpp>
//using boost::math::tools::newton_raphson_iterate;
#include <utility>
namespace boost{ namespace math{
template <class RealType = double, class Policy = policies::policy<> >
class inverse_gaussian_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
inverse_gaussian_distribution(RealType l_mean = 1, RealType l_scale = 1)
: m_mean(l_mean), m_scale(l_scale)
{ // Default is a 1,1 inverse_gaussian distribution.
static const char* function = "boost::math::inverse_gaussian_distribution<%1%>::inverse_gaussian_distribution";
RealType result;
detail::check_scale(function, l_scale, &result, Policy());
detail::check_location(function, l_mean, &result, Policy());
detail::check_x_gt0(function, l_mean, &result, Policy());
}
RealType mean()const
{ // alias for location.
return m_mean; // aka mu
}
// Synonyms, provided to allow generic use of find_location and find_scale.
RealType location()const
{ // location, aka mu.
return m_mean;
}
RealType scale()const
{ // scale, aka lambda.
return m_scale;
}
RealType shape()const
{ // shape, aka phi = lambda/mu.
return m_scale / m_mean;
}
private:
//
// Data members:
//
RealType m_mean; // distribution mean or location, aka mu.
RealType m_scale; // distribution standard deviation or scale, aka lambda.
}; // class normal_distribution
typedef inverse_gaussian_distribution<double> inverse_gaussian;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const inverse_gaussian_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x, zero to max.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(static_cast<RealType>(0.), max_value<RealType>()); // - to + max value.
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const inverse_gaussian_distribution<RealType, Policy>& /*dist*/)
{ // Range of supported values for random variable x, zero to max.
// 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>(static_cast<RealType>(0.), max_value<RealType>()); // - to + max value.
}
template <class RealType, class Policy>
inline RealType pdf(const inverse_gaussian_distribution<RealType, Policy>& dist, const RealType& x)
{ // Probability Density Function
BOOST_MATH_STD_USING // for ADL of std functions
RealType scale = dist.scale();
RealType mean = dist.mean();
RealType result = 0;
static const char* function = "boost::math::pdf(const inverse_gaussian_distribution<%1%>&, %1%)";
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if(false == detail::check_location(function, mean, &result, Policy()))
{
return result;
}
if(false == detail::check_x_gt0(function, mean, &result, Policy()))
{
return result;
}
if(false == detail::check_positive_x(function, x, &result, Policy()))
{
return result;
}
if (x == 0)
{
return 0; // Convenient, even if not defined mathematically.
}
result =
sqrt(scale / (constants::two_pi<RealType>() * x * x * x))
* exp(-scale * (x - mean) * (x - mean) / (2 * x * mean * mean));
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const inverse_gaussian_distribution<RealType, Policy>& dist, const RealType& x)
{ // Cumulative Density Function.
BOOST_MATH_STD_USING // for ADL of std functions.
RealType scale = dist.scale();
RealType mean = dist.mean();
static const char* function = "boost::math::cdf(const inverse_gaussian_distribution<%1%>&, %1%)";
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if(false == detail::check_location(function, mean, &result, Policy()))
{
return result;
}
if (false == detail::check_x_gt0(function, mean, &result, Policy()))
{
return result;
}
if(false == detail::check_positive_x(function, x, &result, Policy()))
{
return result;
}
if (x == 0)
{
return 0; // Convenient, even if not defined mathematically.
}
// Problem with this formula for large scale > 1000 or small x,
//result = 0.5 * (erf(sqrt(scale / x) * ((x / mean) - 1) / constants::root_two<RealType>(), Policy()) + 1)
// + exp(2 * scale / mean) / 2
// * (1 - erf(sqrt(scale / x) * (x / mean + 1) / constants::root_two<RealType>(), Policy()));
// so use normal distribution version:
// Wikipedia CDF equation http://en.wikipedia.org/wiki/Inverse_Gaussian_distribution.
normal_distribution<RealType> n01;
RealType n0 = sqrt(scale / x);
n0 *= ((x / mean) -1);
RealType n1 = cdf(n01, n0);
RealType expfactor = exp(2 * scale / mean);
RealType n3 = - sqrt(scale / x);
n3 *= (x / mean) + 1;
RealType n4 = cdf(n01, n3);
result = n1 + expfactor * n4;
return result;
} // cdf
template <class RealType, class Policy>
struct inverse_gaussian_quantile_functor
{
inverse_gaussian_quantile_functor(const boost::math::inverse_gaussian_distribution<RealType, Policy> dist, RealType const& p)
: distribution(dist), prob(p)
{
}
boost::math::tuple<RealType, RealType> operator()(RealType const& x)
{
RealType c = cdf(distribution, x);
RealType fx = c - prob; // Difference cdf - value - to minimize.
RealType dx = pdf(distribution, x); // pdf is 1st derivative.
// return both function evaluation difference f(x) and 1st derivative f'(x).
return boost::math::make_tuple(fx, dx);
}
private:
const boost::math::inverse_gaussian_distribution<RealType, Policy> distribution;
RealType prob;
};
template <class RealType, class Policy>
struct inverse_gaussian_quantile_complement_functor
{
inverse_gaussian_quantile_complement_functor(const boost::math::inverse_gaussian_distribution<RealType, Policy> dist, RealType const& p)
: distribution(dist), prob(p)
{
}
boost::math::tuple<RealType, RealType> operator()(RealType const& x)
{
RealType c = cdf(complement(distribution, x));
RealType fx = c - prob; // Difference cdf - value - to minimize.
RealType dx = -pdf(distribution, x); // pdf is 1st derivative.
// return both function evaluation difference f(x) and 1st derivative f'(x).
//return std::tr1::make_tuple(fx, dx); if available.
return boost::math::make_tuple(fx, dx);
}
private:
const boost::math::inverse_gaussian_distribution<RealType, Policy> distribution;
RealType prob;
};
namespace detail
{
template <class RealType>
inline RealType guess_ig(RealType p, RealType mu = 1, RealType lambda = 1)
{ // guess at random variate value x for inverse gaussian quantile.
BOOST_MATH_STD_USING
using boost::math::policies::policy;
// Error type.
using boost::math::policies::overflow_error;
// Action.
using boost::math::policies::ignore_error;
typedef policy<
overflow_error<ignore_error> // Ignore overflow (return infinity)
> no_overthrow_policy;
RealType x; // result is guess at random variate value x.
RealType phi = lambda / mu;
if (phi > 2.)
{ // Big phi, so starting to look like normal Gaussian distribution.
// x=(qnorm(p,0,1,true,false) - 0.5 * sqrt(mu/lambda)) / sqrt(lambda/mu);
// Whitmore, G.A. and Yalovsky, M.
// A normalising logarithmic transformation for inverse Gaussian random variables,
// Technometrics 20-2, 207-208 (1978), but using expression from
// V Seshadri, Inverse Gaussian distribution (1998) ISBN 0387 98618 9, page 6.
normal_distribution<RealType, no_overthrow_policy> n01;
x = mu * exp(quantile(n01, p) / sqrt(phi) - 1/(2 * phi));
}
else
{ // phi < 2 so much less symmetrical with long tail,
// so use gamma distribution as an approximation.
using boost::math::gamma_distribution;
// Define the distribution, using gamma_nooverflow:
typedef gamma_distribution<RealType, no_overthrow_policy> gamma_nooverflow;
gamma_nooverflow g(static_cast<RealType>(0.5), static_cast<RealType>(1.));
// gamma_nooverflow g(static_cast<RealType>(0.5), static_cast<RealType>(1.));
// R qgamma(0.2, 0.5, 1) 0.0320923
RealType qg = quantile(complement(g, p));
//RealType qg1 = qgamma(1.- p, 0.5, 1.0, true, false);
x = lambda / (qg * 2);
//
if (x > mu/2) // x > mu /2?
{ // x too large for the gamma approximation to work well.
//x = qgamma(p, 0.5, 1.0); // qgamma(0.270614, 0.5, 1) = 0.05983807
RealType q = quantile(g, p);
// x = mu * exp(q * static_cast<RealType>(0.1)); // Said to improve at high p
// x = mu * x; // Improves at high p?
x = mu * exp(q / sqrt(phi) - 1/(2 * phi));
}
}
return x;
} // guess_ig
} // namespace detail
template <class RealType, class Policy>
inline RealType quantile(const inverse_gaussian_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions.
// No closed form exists so guess and use Newton Raphson iteration.
RealType mean = dist.mean();
RealType scale = dist.scale();
static const char* function = "boost::math::quantile(const inverse_gaussian_distribution<%1%>&, %1%)";
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
return result;
if(false == detail::check_location(function, mean, &result, Policy()))
return result;
if (false == detail::check_x_gt0(function, mean, &result, Policy()))
return result;
if(false == detail::check_probability(function, p, &result, Policy()))
return result;
if (p == 0)
{
return 0; // Convenient, even if not defined mathematically?
}
if (p == 1)
{ // overflow
result = policies::raise_overflow_error<RealType>(function,
"probability parameter is 1, but must be < 1!", Policy());
return result; // std::numeric_limits<RealType>::infinity();
}
RealType guess = detail::guess_ig(p, dist.mean(), dist.scale());
using boost::math::tools::max_value;
RealType min = 0.; // Minimum possible value is bottom of range of distribution.
RealType max = max_value<RealType>();// Maximum possible value is top of range.
// int digits = std::numeric_limits<RealType>::digits; // Maximum possible binary digits accuracy for type T.
// digits used to control how accurate to try to make the result.
// To allow user to control accuracy versus speed,
int get_digits = policies::digits<RealType, Policy>();// get digits from policy,
boost::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
using boost::math::tools::newton_raphson_iterate;
result =
newton_raphson_iterate(inverse_gaussian_quantile_functor<RealType, Policy>(dist, p), guess, min, max, get_digits, m);
return result;
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<inverse_gaussian_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions.
RealType scale = c.dist.scale();
RealType mean = c.dist.mean();
RealType x = c.param;
static const char* function = "boost::math::cdf(const complement(inverse_gaussian_distribution<%1%>&), %1%)";
// infinite arguments not supported.
//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 = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
return result;
if(false == detail::check_location(function, mean, &result, Policy()))
return result;
if (false == detail::check_x_gt0(function, mean, &result, Policy()))
return result;
if(false == detail::check_positive_x(function, x, &result, Policy()))
return result;
normal_distribution<RealType> n01;
RealType n0 = sqrt(scale / x);
n0 *= ((x / mean) -1);
RealType cdf_1 = cdf(complement(n01, n0));
RealType expfactor = exp(2 * scale / mean);
RealType n3 = - sqrt(scale / x);
n3 *= (x / mean) + 1;
//RealType n5 = +sqrt(scale/x) * ((x /mean) + 1); // note now positive sign.
RealType n6 = cdf(complement(n01, +sqrt(scale/x) * ((x /mean) + 1)));
// RealType n4 = cdf(n01, n3); // =
result = cdf_1 - expfactor * n6;
return result;
} // cdf complement
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<inverse_gaussian_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions
RealType scale = c.dist.scale();
RealType mean = c.dist.mean();
static const char* function = "boost::math::quantile(const complement(inverse_gaussian_distribution<%1%>&), %1%)";
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
return result;
if(false == detail::check_location(function, mean, &result, Policy()))
return result;
if (false == detail::check_x_gt0(function, mean, &result, Policy()))
return result;
RealType q = c.param;
if(false == detail::check_probability(function, q, &result, Policy()))
return result;
RealType guess = detail::guess_ig(q, mean, scale);
// Complement.
using boost::math::tools::max_value;
RealType min = 0.; // Minimum possible value is bottom of range of distribution.
RealType max = max_value<RealType>();// Maximum possible value is top of range.
// int digits = std::numeric_limits<RealType>::digits; // Maximum possible binary digits accuracy for type T.
// digits used to control how accurate to try to make the result.
int get_digits = policies::digits<RealType, Policy>();
boost::uintmax_t m = policies::get_max_root_iterations<Policy>();
using boost::math::tools::newton_raphson_iterate;
result =
newton_raphson_iterate(inverse_gaussian_quantile_complement_functor<RealType, Policy>(c.dist, q), guess, min, max, get_digits, m);
return result;
} // quantile
template <class RealType, class Policy>
inline RealType mean(const inverse_gaussian_distribution<RealType, Policy>& dist)
{ // aka mu
return dist.mean();
}
template <class RealType, class Policy>
inline RealType scale(const inverse_gaussian_distribution<RealType, Policy>& dist)
{ // aka lambda
return dist.scale();
}
template <class RealType, class Policy>
inline RealType shape(const inverse_gaussian_distribution<RealType, Policy>& dist)
{ // aka phi
return dist.shape();
}
template <class RealType, class Policy>
inline RealType standard_deviation(const inverse_gaussian_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING
RealType scale = dist.scale();
RealType mean = dist.mean();
RealType result = sqrt(mean * mean * mean / scale);
return result;
}
template <class RealType, class Policy>
inline RealType mode(const inverse_gaussian_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING
RealType scale = dist.scale();
RealType mean = dist.mean();
RealType result = mean * (sqrt(1 + (9 * mean * mean)/(4 * scale * scale))
- 3 * mean / (2 * scale));
return result;
}
template <class RealType, class Policy>
inline RealType skewness(const inverse_gaussian_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING
RealType scale = dist.scale();
RealType mean = dist.mean();
RealType result = 3 * sqrt(mean/scale);
return result;
}
template <class RealType, class Policy>
inline RealType kurtosis(const inverse_gaussian_distribution<RealType, Policy>& dist)
{
RealType scale = dist.scale();
RealType mean = dist.mean();
RealType result = 15 * mean / scale -3;
return result;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const inverse_gaussian_distribution<RealType, Policy>& dist)
{
RealType scale = dist.scale();
RealType mean = dist.mean();
RealType result = 15 * mean / scale;
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_STATS_INVERSE_GAUSSIAN_HPP

View File

@@ -0,0 +1,350 @@
// Copyright Thijs van den Berg, 2008.
// Copyright John Maddock 2008.
// Copyright Paul A. Bristow 2008, 2014.
// 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 module implements the Laplace distribution.
// Weisstein, Eric W. "Laplace Distribution." From MathWorld--A Wolfram Web Resource.
// http://mathworld.wolfram.com/LaplaceDistribution.html
// http://en.wikipedia.org/wiki/Laplace_distribution
//
// Abramowitz and Stegun 1972, p 930
// http://www.math.sfu.ca/~cbm/aands/page_930.htm
#ifndef BOOST_STATS_LAPLACE_HPP
#define BOOST_STATS_LAPLACE_HPP
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/constants/constants.hpp>
#include <limits>
namespace boost{ namespace math{
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:4127) // conditional expression is constant
#endif
template <class RealType = double, class Policy = policies::policy<> >
class laplace_distribution
{
public:
// ----------------------------------
// public Types
// ----------------------------------
typedef RealType value_type;
typedef Policy policy_type;
// ----------------------------------
// Constructor(s)
// ----------------------------------
laplace_distribution(RealType l_location = 0, RealType l_scale = 1)
: m_location(l_location), m_scale(l_scale)
{
RealType result;
check_parameters("boost::math::laplace_distribution<%1%>::laplace_distribution()", &result);
}
// ----------------------------------
// Public functions
// ----------------------------------
RealType location() const
{
return m_location;
}
RealType scale() const
{
return m_scale;
}
bool check_parameters(const char* function, RealType* result) const
{
if(false == detail::check_scale(function, m_scale, result, Policy())) return false;
if(false == detail::check_location(function, m_location, result, Policy())) return false;
return true;
}
private:
RealType m_location;
RealType m_scale;
}; // class laplace_distribution
//
// Convenient type synonym for double.
typedef laplace_distribution<double> laplace;
//
// Non-member functions.
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const laplace_distribution<RealType, Policy>&)
{
if (std::numeric_limits<RealType>::has_infinity)
{ // Can use infinity.
return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
}
else
{ // Can only use max_value.
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 laplace_distribution<RealType, Policy>&)
{
if (std::numeric_limits<RealType>::has_infinity)
{ // Can Use infinity.
return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
}
else
{ // Can only use max_value.
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 laplace_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // for ADL of std functions
// Checking function argument
RealType result = 0;
const char* function = "boost::math::pdf(const laplace_distribution<%1%>&, %1%))";
// Check scale and location.
if (false == dist.check_parameters(function, &result)) return result;
// Special pdf values.
if((boost::math::isinf)(x))
{
return 0; // pdf + and - infinity is zero.
}
if (false == detail::check_x(function, x, &result, Policy())) return result;
// General case
RealType scale( dist.scale() );
RealType location( dist.location() );
RealType exponent = x - location;
if (exponent>0) exponent = -exponent;
exponent /= scale;
result = exp(exponent);
result /= 2 * scale;
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING // For ADL of std functions.
RealType result = 0;
// Checking function argument.
const char* function = "boost::math::cdf(const laplace_distribution<%1%>&, %1%)";
// Check scale and location.
if (false == dist.check_parameters(function, &result)) return result;
// Special cdf values:
if((boost::math::isinf)(x))
{
if(x < 0) return 0; // -infinity.
return 1; // + infinity.
}
if (false == detail::check_x(function, x, &result, Policy())) return result;
// General cdf values
RealType scale( dist.scale() );
RealType location( dist.location() );
if (x < location)
{
result = exp( (x-location)/scale )/2;
}
else
{
result = 1 - exp( (location-x)/scale )/2;
}
return result;
} // cdf
template <class RealType, class Policy>
inline RealType quantile(const laplace_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING // for ADL of std functions.
// Checking function argument
RealType result = 0;
const char* function = "boost::math::quantile(const laplace_distribution<%1%>&, %1%)";
if (false == dist.check_parameters(function, &result)) return result;
if(false == detail::check_probability(function, p, &result, Policy())) return result;
// Extreme values of p:
if(p == 0)
{
result = policies::raise_overflow_error<RealType>(function,
"probability parameter is 0, but must be > 0!", Policy());
return -result; // -std::numeric_limits<RealType>::infinity();
}
if(p == 1)
{
result = policies::raise_overflow_error<RealType>(function,
"probability parameter is 1, but must be < 1!", Policy());
return result; // std::numeric_limits<RealType>::infinity();
}
// Calculate Quantile
RealType scale( dist.scale() );
RealType location( dist.location() );
if (p - 0.5 < 0.0)
result = location + scale*log( static_cast<RealType>(p*2) );
else
result = location - scale*log( static_cast<RealType>(-p*2 + 2) );
return result;
} // quantile
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)
{
// Calculate complement of cdf.
BOOST_MATH_STD_USING // for ADL of std functions
RealType scale = c.dist.scale();
RealType location = c.dist.location();
RealType x = c.param;
RealType result = 0;
// Checking function argument.
const char* function = "boost::math::cdf(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
// Check scale and location.
//if(false == detail::check_scale(function, scale, result, Policy())) return false;
//if(false == detail::check_location(function, location, result, Policy())) return false;
if (false == c.dist.check_parameters(function, &result)) return result;
// Special cdf values.
if((boost::math::isinf)(x))
{
if(x < 0) return 1; // cdf complement -infinity is unity.
return 0; // cdf complement +infinity is zero.
}
if(false == detail::check_x(function, x, &result, Policy()))return result;
// Cdf interval value.
if (-x < -location)
{
result = exp( (-x+location)/scale )/2;
}
else
{
result = 1 - exp( (-location+x)/scale )/2;
}
return result;
} // cdf complement
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING // for ADL of std functions.
// Calculate quantile.
RealType scale = c.dist.scale();
RealType location = c.dist.location();
RealType q = c.param;
RealType result = 0;
// Checking function argument.
const char* function = "quantile(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
if (false == c.dist.check_parameters(function, &result)) return result;
// Extreme values.
if(q == 0)
{
return std::numeric_limits<RealType>::infinity();
}
if(q == 1)
{
return -std::numeric_limits<RealType>::infinity();
}
if(false == detail::check_probability(function, q, &result, Policy())) return result;
if (0.5 - q < 0.0)
result = location + scale*log( static_cast<RealType>(-q*2 + 2) );
else
result = location - scale*log( static_cast<RealType>(q*2) );
return result;
} // quantile
template <class RealType, class Policy>
inline RealType mean(const laplace_distribution<RealType, Policy>& dist)
{
return dist.location();
}
template <class RealType, class Policy>
inline RealType standard_deviation(const laplace_distribution<RealType, Policy>& dist)
{
return constants::root_two<RealType>() * dist.scale();
}
template <class RealType, class Policy>
inline RealType mode(const laplace_distribution<RealType, Policy>& dist)
{
return dist.location();
}
template <class RealType, class Policy>
inline RealType median(const laplace_distribution<RealType, Policy>& dist)
{
return dist.location();
}
template <class RealType, class Policy>
inline RealType skewness(const laplace_distribution<RealType, Policy>& /*dist*/)
{
return 0;
}
template <class RealType, class Policy>
inline RealType kurtosis(const laplace_distribution<RealType, Policy>& /*dist*/)
{
return 6;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const laplace_distribution<RealType, Policy>& /*dist*/)
{
return 3;
}
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // 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_LAPLACE_HPP

View File

@@ -0,0 +1,299 @@
// Copyright 2008 Gautam Sewani
//
// 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_LOGISTIC
#define BOOST_MATH_DISTRIBUTIONS_LOGISTIC
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/distributions/complement.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/constants/constants.hpp>
#include <utility>
namespace boost { namespace math {
template <class RealType = double, class Policy = policies::policy<> >
class logistic_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
logistic_distribution(RealType l_location=0, RealType l_scale=1) // Constructor.
: m_location(l_location), m_scale(l_scale)
{
static const char* function = "boost::math::logistic_distribution<%1%>::logistic_distribution";
RealType result;
detail::check_scale(function, l_scale, &result, Policy());
detail::check_location(function, l_location, &result, Policy());
}
// Accessor functions.
RealType scale()const
{
return m_scale;
}
RealType location()const
{
return m_location;
}
private:
// Data members:
RealType m_location; // distribution location aka mu.
RealType m_scale; // distribution scale aka s.
}; // class logistic_distribution
typedef logistic_distribution<double> logistic;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const logistic_distribution<RealType, Policy>& /* dist */)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(
std::numeric_limits<RealType>::has_infinity ? -std::numeric_limits<RealType>::infinity() : -max_value<RealType>(),
std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : max_value<RealType>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const logistic_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 + infinity
}
template <class RealType, class Policy>
inline RealType pdf(const logistic_distribution<RealType, Policy>& dist, const RealType& x)
{
static const char* function = "boost::math::pdf(const logistic_distribution<%1%>&, %1%)";
RealType scale = dist.scale();
RealType location = dist.location();
RealType result = 0;
if(false == detail::check_scale(function, scale , &result, Policy()))
{
return result;
}
if(false == detail::check_location(function, location, &result, Policy()))
{
return result;
}
if((boost::math::isinf)(x))
{
return 0; // pdf + and - infinity is zero.
}
if(false == detail::check_x(function, x, &result, Policy()))
{
return result;
}
BOOST_MATH_STD_USING
RealType exp_term = (location - x) / scale;
if(fabs(exp_term) > tools::log_max_value<RealType>())
return 0;
exp_term = exp(exp_term);
if((exp_term * scale > 1) && (exp_term > tools::max_value<RealType>() / (scale * exp_term)))
return 1 / (scale * exp_term);
return (exp_term) / (scale * (1 + exp_term) * (1 + exp_term));
}
template <class RealType, class Policy>
inline RealType cdf(const logistic_distribution<RealType, Policy>& dist, const RealType& x)
{
RealType scale = dist.scale();
RealType location = dist.location();
RealType result = 0; // of checks.
static const char* function = "boost::math::cdf(const logistic_distribution<%1%>&, %1%)";
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if(false == detail::check_location(function, location, &result, Policy()))
{
return result;
}
if((boost::math::isinf)(x))
{
if(x < 0) return 0; // -infinity
return 1; // + infinity
}
if(false == detail::check_x(function, x, &result, Policy()))
{
return result;
}
BOOST_MATH_STD_USING
RealType power = (location - x) / scale;
if(power > tools::log_max_value<RealType>())
return 0;
if(power < -tools::log_max_value<RealType>())
return 1;
return 1 / (1 + exp(power));
}
template <class RealType, class Policy>
inline RealType quantile(const logistic_distribution<RealType, Policy>& dist, const RealType& p)
{
BOOST_MATH_STD_USING
RealType location = dist.location();
RealType scale = dist.scale();
static const char* function = "boost::math::quantile(const logistic_distribution<%1%>&, %1%)";
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
return result;
if(false == detail::check_location(function, location, &result, Policy()))
return result;
if(false == detail::check_probability(function, p, &result, Policy()))
return result;
if(p == 0)
{
return -policies::raise_overflow_error<RealType>(function,"probability argument is 0, must be >0 and <1",Policy());
}
if(p == 1)
{
return policies::raise_overflow_error<RealType>(function,"probability argument is 1, must be >0 and <1",Policy());
}
//Expressions to try
//return location+scale*log(p/(1-p));
//return location+scale*log1p((2*p-1)/(1-p));
//return location - scale*log( (1-p)/p);
//return location - scale*log1p((1-2*p)/p);
//return -scale*log(1/p-1) + location;
return location - scale * log((1 - p) / p);
} // RealType quantile(const logistic_distribution<RealType, Policy>& dist, const RealType& p)
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<logistic_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING
RealType location = c.dist.location();
RealType scale = c.dist.scale();
RealType x = c.param;
static const char* function = "boost::math::cdf(const complement(logistic_distribution<%1%>&), %1%)";
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if(false == detail::check_location(function, location, &result, Policy()))
{
return result;
}
if((boost::math::isinf)(x))
{
if(x < 0) return 1; // cdf complement -infinity is unity.
return 0; // cdf complement +infinity is zero.
}
if(false == detail::check_x(function, x, &result, Policy()))
{
return result;
}
RealType power = (x - location) / scale;
if(power > tools::log_max_value<RealType>())
return 0;
if(power < -tools::log_max_value<RealType>())
return 1;
return 1 / (1 + exp(power));
}
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<logistic_distribution<RealType, Policy>, RealType>& c)
{
BOOST_MATH_STD_USING
RealType scale = c.dist.scale();
RealType location = c.dist.location();
static const char* function = "boost::math::quantile(const complement(logistic_distribution<%1%>&), %1%)";
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
return result;
if(false == detail::check_location(function, location, &result, Policy()))
return result;
RealType q = c.param;
if(false == detail::check_probability(function, q, &result, Policy()))
return result;
using boost::math::tools::max_value;
if(q == 1)
{
return -policies::raise_overflow_error<RealType>(function,"probability argument is 1, but must be >0 and <1",Policy());
}
if(q == 0)
{
return policies::raise_overflow_error<RealType>(function,"probability argument is 0, but must be >0 and <1",Policy());
}
//Expressions to try
//return location+scale*log((1-q)/q);
return location + scale * log((1 - q) / q);
//return location-scale*log(q/(1-q));
//return location-scale*log1p((2*q-1)/(1-q));
//return location+scale*log(1/q-1);
//return location+scale*log1p(1/q-2);
}
template <class RealType, class Policy>
inline RealType mean(const logistic_distribution<RealType, Policy>& dist)
{
return dist.location();
} // RealType mean(const logistic_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType variance(const logistic_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING
RealType scale = dist.scale();
return boost::math::constants::pi<RealType>()*boost::math::constants::pi<RealType>()*scale*scale/3;
} // RealType variance(const logistic_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType mode(const logistic_distribution<RealType, Policy>& dist)
{
return dist.location();
}
template <class RealType, class Policy>
inline RealType median(const logistic_distribution<RealType, Policy>& dist)
{
return dist.location();
}
template <class RealType, class Policy>
inline RealType skewness(const logistic_distribution<RealType, Policy>& /*dist*/)
{
return 0;
} // RealType skewness(const logistic_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType kurtosis_excess(const logistic_distribution<RealType, Policy>& /*dist*/)
{
return static_cast<RealType>(6)/5;
} // RealType kurtosis_excess(const logistic_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType kurtosis(const logistic_distribution<RealType, Policy>& dist)
{
return kurtosis_excess(dist) + 3;
} // RealType kurtosis_excess(const logistic_distribution<RealType, Policy>& dist)
}}
// Must come at the end:
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_MATH_DISTRIBUTIONS_LOGISTIC

View File

@@ -0,0 +1,341 @@
// 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 l_location = 0, RealType l_scale = 1)
: m_location(l_location), m_scale(l_scale)
{
RealType result;
detail::check_scale("boost::math::lognormal_distribution<%1%>::lognormal_distribution", l_scale, &result, Policy());
detail::check_location("boost::math::lognormal_distribution<%1%>::lognormal_distribution", l_location, &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>(static_cast<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>(static_cast<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 = 0;
if(0 == detail::check_scale(function, sigma, &result, Policy()))
return result;
if(0 == detail::check_location(function, mu, &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 = 0;
if(0 == detail::check_scale(function, dist.scale(), &result, Policy()))
return result;
if(0 == detail::check_location(function, dist.location(), &result, Policy()))
return 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 = 0;
if(0 == detail::check_scale(function, dist.scale(), &result, Policy()))
return result;
if(0 == detail::check_location(function, dist.location(), &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());
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 = 0;
if(0 == detail::check_scale(function, c.dist.scale(), &result, Policy()))
return result;
if(0 == detail::check_location(function, c.dist.location(), &result, Policy()))
return 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 = 0;
if(0 == detail::check_scale(function, c.dist.scale(), &result, Policy()))
return result;
if(0 == detail::check_location(function, c.dist.location(), &result, Policy()))
return 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 = 0;
if(0 == detail::check_scale("boost::math::mean(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
if(0 == detail::check_location("boost::math::mean(const lognormal_distribution<%1%>&)", mu, &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 = 0;
if(0 == detail::check_scale("boost::math::variance(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
if(0 == detail::check_location("boost::math::variance(const lognormal_distribution<%1%>&)", mu, &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 = 0;
if(0 == detail::check_scale("boost::math::mode(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
if(0 == detail::check_location("boost::math::mode(const lognormal_distribution<%1%>&)", mu, &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 = 0;
if(0 == detail::check_scale("boost::math::skewness(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
if(0 == detail::check_location("boost::math::skewness(const lognormal_distribution<%1%>&)", dist.location(), &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 = 0;
if(0 == detail::check_scale("boost::math::kurtosis(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
if(0 == detail::check_location("boost::math::kurtosis(const lognormal_distribution<%1%>&)", dist.location(), &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 = 0;
if(0 == detail::check_scale("boost::math::kurtosis_excess(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
return result;
if(0 == detail::check_location("boost::math::kurtosis_excess(const lognormal_distribution<%1%>&)", dist.location(), &result, Policy()))
return result;
return exp(4 * ss) + 2 * exp(3 * ss) + 3 * exp(2 * ss) - 6;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_STUDENTS_T_HPP

View File

@@ -0,0 +1,607 @@
// 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 = 0; // 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 = 0; // 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 = 0;
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 = 0;
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>(static_cast<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>(static_cast<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 = 0;
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 = 0;
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 = 0;
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 = 0;
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;
}
if(p == 0)
{ // Would need +infinity failures for total confidence.
result = policies::raise_overflow_error<RealType>(
function,
"Success fraction 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
}
/*
// 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, RealType(1-p), P, RealType(1-P), Policy());
if(guess < 10)
{
//
// Cornish-Fisher Negative binomial approximation not accurate in this area:
//
guess = (std::min)(RealType(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,
false,
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 = 0;
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 == 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
}
if (-Q <= boost::math::powm1(dist.success_fraction(), dist.successes(), Policy()))
{ // q <= cdf(complement(dist, 0)) == pdf(dist, 0)
return 0; //
}
if(p == 0)
{ // Success fraction is 0 so infinite failures to achieve certainty.
// Would need +infinity failures for total confidence.
result = policies::raise_overflow_error<RealType>(
function,
"Success fraction 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, RealType(1-p), RealType(1-Q), Q, Policy());
if(guess < 10)
{
//
// Cornish-Fisher Negative binomial approximation not accurate in this area:
//
guess = (std::min)(RealType(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,
Q,
true,
guess,
factor,
RealType(1),
discrete_type(),
max_iter);
} // quantile complement
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#if defined (BOOST_MSVC)
# pragma warning(pop)
#endif
#endif // BOOST_MATH_SPECIAL_NEGATIVE_BINOMIAL_HPP

View File

@@ -0,0 +1,929 @@
// boost\math\distributions\non_central_beta.hpp
// Copyright John Maddock 2008.
// 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_SPECIAL_NON_CENTRAL_BETA_HPP
#define BOOST_MATH_SPECIAL_NON_CENTRAL_BETA_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/beta.hpp> // for incomplete gamma. gamma_q
#include <boost/math/distributions/complement.hpp> // complements
#include <boost/math/distributions/beta.hpp> // central distribution
#include <boost/math/distributions/detail/generic_mode.hpp>
#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.
#include <boost/math/tools/series.hpp>
namespace boost
{
namespace math
{
template <class RealType, class Policy>
class non_central_beta_distribution;
namespace detail{
template <class T, class Policy>
T non_central_beta_p(T a, T b, T lam, T x, T y, const Policy& pol, T init_val = 0)
{
BOOST_MATH_STD_USING
using namespace boost::math;
//
// Variables come first:
//
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T l2 = lam / 2;
//
// k is the starting point for iteration, and is the
// maximum of the poisson weighting term,
// note that unlike other similar code, we do not set
// k to zero, when l2 is small, as forward iteration
// is unstable:
//
int k = itrunc(l2);
if(k == 0)
k = 1;
// Starting Poisson weight:
T pois = gamma_p_derivative(T(k+1), l2, pol);
if(pois == 0)
return init_val;
// recurance term:
T xterm;
// Starting beta term:
T beta = x < y
? detail::ibeta_imp(T(a + k), b, x, pol, false, true, &xterm)
: detail::ibeta_imp(b, T(a + k), y, pol, true, true, &xterm);
xterm *= y / (a + b + k - 1);
T poisf(pois), betaf(beta), xtermf(xterm);
T sum = init_val;
if((beta == 0) && (xterm == 0))
return init_val;
//
// Backwards recursion first, this is the stable
// direction for recursion:
//
T last_term = 0;
boost::uintmax_t count = k;
for(int i = k; i >= 0; --i)
{
T term = beta * pois;
sum += term;
if(((fabs(term/sum) < errtol) && (last_term >= term)) || (term == 0))
{
count = k - i;
break;
}
pois *= i / l2;
beta += xterm;
xterm *= (a + i - 1) / (x * (a + b + i - 2));
last_term = term;
}
for(int i = k + 1; ; ++i)
{
poisf *= l2 / i;
xtermf *= (x * (a + b + i - 2)) / (a + i - 1);
betaf -= xtermf;
T term = poisf * betaf;
sum += term;
if((fabs(term/sum) < errtol) || (term == 0))
{
break;
}
if(static_cast<boost::uintmax_t>(count + i - k) > max_iter)
{
return policies::raise_evaluation_error(
"cdf(non_central_beta_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
}
}
return sum;
}
template <class T, class Policy>
T non_central_beta_q(T a, T b, T lam, T x, T y, const Policy& pol, T init_val = 0)
{
BOOST_MATH_STD_USING
using namespace boost::math;
//
// Variables come first:
//
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T l2 = lam / 2;
//
// k is the starting point for iteration, and is the
// maximum of the poisson weighting term:
//
int k = itrunc(l2);
T pois;
if(k <= 30)
{
//
// Might as well start at 0 since we'll likely have this number of terms anyway:
//
if(a + b > 1)
k = 0;
else if(k == 0)
k = 1;
}
if(k == 0)
{
// Starting Poisson weight:
pois = exp(-l2);
}
else
{
// Starting Poisson weight:
pois = gamma_p_derivative(T(k+1), l2, pol);
}
if(pois == 0)
return init_val;
// recurance term:
T xterm;
// Starting beta term:
T beta = x < y
? detail::ibeta_imp(T(a + k), b, x, pol, true, true, &xterm)
: detail::ibeta_imp(b, T(a + k), y, pol, false, true, &xterm);
xterm *= y / (a + b + k - 1);
T poisf(pois), betaf(beta), xtermf(xterm);
T sum = init_val;
if((beta == 0) && (xterm == 0))
return init_val;
//
// Forwards recursion first, this is the stable
// direction for recursion, and the location
// of the bulk of the sum:
//
T last_term = 0;
boost::uintmax_t count = 0;
for(int i = k + 1; ; ++i)
{
poisf *= l2 / i;
xtermf *= (x * (a + b + i - 2)) / (a + i - 1);
betaf += xtermf;
T term = poisf * betaf;
sum += term;
if((fabs(term/sum) < errtol) && (last_term >= term))
{
count = i - k;
break;
}
if(static_cast<boost::uintmax_t>(i - k) > max_iter)
{
return policies::raise_evaluation_error(
"cdf(non_central_beta_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
}
last_term = term;
}
for(int i = k; i >= 0; --i)
{
T term = beta * pois;
sum += term;
if(fabs(term/sum) < errtol)
{
break;
}
if(static_cast<boost::uintmax_t>(count + k - i) > max_iter)
{
return policies::raise_evaluation_error(
"cdf(non_central_beta_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
}
pois *= i / l2;
beta -= xterm;
xterm *= (a + i - 1) / (x * (a + b + i - 2));
}
return sum;
}
template <class RealType, class Policy>
inline RealType non_central_beta_cdf(RealType x, RealType y, RealType a, RealType b, RealType l, bool invert, const Policy&)
{
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
BOOST_MATH_STD_USING
if(x == 0)
return invert ? 1.0f : 0.0f;
if(y == 0)
return invert ? 0.0f : 1.0f;
value_type result;
value_type c = a + b + l / 2;
value_type cross = 1 - (b / c) * (1 + l / (2 * c * c));
if(l == 0)
result = cdf(boost::math::beta_distribution<RealType, Policy>(a, b), x);
else if(x > cross)
{
// Complement is the smaller of the two:
result = detail::non_central_beta_q(
static_cast<value_type>(a),
static_cast<value_type>(b),
static_cast<value_type>(l),
static_cast<value_type>(x),
static_cast<value_type>(y),
forwarding_policy(),
static_cast<value_type>(invert ? 0 : -1));
invert = !invert;
}
else
{
result = detail::non_central_beta_p(
static_cast<value_type>(a),
static_cast<value_type>(b),
static_cast<value_type>(l),
static_cast<value_type>(x),
static_cast<value_type>(y),
forwarding_policy(),
static_cast<value_type>(invert ? -1 : 0));
}
if(invert)
result = -result;
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
"boost::math::non_central_beta_cdf<%1%>(%1%, %1%, %1%)");
}
template <class T, class Policy>
struct nc_beta_quantile_functor
{
nc_beta_quantile_functor(const non_central_beta_distribution<T,Policy>& d, T t, bool c)
: dist(d), target(t), comp(c) {}
T operator()(const T& x)
{
return comp ?
T(target - cdf(complement(dist, x)))
: T(cdf(dist, x) - target);
}
private:
non_central_beta_distribution<T,Policy> dist;
T target;
bool comp;
};
//
// This is more or less a copy of bracket_and_solve_root, but
// modified to search only the interval [0,1] using similar
// heuristics.
//
template <class F, class T, class Tol, class Policy>
std::pair<T, T> bracket_and_solve_root_01(F f, const T& guess, T factor, bool rising, Tol tol, boost::uintmax_t& max_iter, const Policy& pol)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::tools::bracket_and_solve_root_01<%1%>";
//
// Set up inital brackets:
//
T a = guess;
T b = a;
T fa = f(a);
T fb = fa;
//
// Set up invocation count:
//
boost::uintmax_t count = max_iter - 1;
if((fa < 0) == (guess < 0 ? !rising : rising))
{
//
// Zero is to the right of b, so walk upwards
// until we find it:
//
while((boost::math::sign)(fb) == (boost::math::sign)(fa))
{
if(count == 0)
{
b = policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol);
return std::make_pair(a, b);
}
//
// Heuristic: every 20 iterations we double the growth factor in case the
// initial guess was *really* bad !
//
if((max_iter - count) % 20 == 0)
factor *= 2;
//
// Now go ahead and move are guess by "factor",
// we do this by reducing 1-guess by factor:
//
a = b;
fa = fb;
b = 1 - ((1 - b) / factor);
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((boost::math::sign)(fb) == (boost::math::sign)(fa))
{
if(fabs(a) < tools::min_value<T>())
{
// Escape route just in case the answer is zero!
max_iter -= count;
max_iter += 1;
return a > 0 ? std::make_pair(T(0), T(a)) : std::make_pair(T(a), T(0));
}
if(count == 0)
{
a = policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol);
return std::make_pair(a, b);
}
//
// Heuristic: every 20 iterations we double the growth factor in case the
// initial guess was *really* bad !
//
if((max_iter - count) % 20 == 0)
factor *= 2;
//
// Now go ahead and move are guess by "factor":
//
b = a;
fb = fa;
a /= factor;
fa = f(a);
--count;
BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count);
}
}
max_iter -= count;
max_iter += 1;
std::pair<T, T> r = toms748_solve(
f,
(a < 0 ? b : a),
(a < 0 ? a : b),
(a < 0 ? fb : fa),
(a < 0 ? fa : fb),
tol,
count,
pol);
max_iter += count;
BOOST_MATH_INSTRUMENT_CODE("max_iter = " << max_iter << " count = " << count);
return r;
}
template <class RealType, class Policy>
RealType nc_beta_quantile(const non_central_beta_distribution<RealType, Policy>& dist, const RealType& p, bool comp)
{
static const char* function = "quantile(non_central_beta_distribution<%1%>, %1%)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
value_type a = dist.alpha();
value_type b = dist.beta();
value_type l = dist.non_centrality();
value_type r;
if(!beta_detail::check_alpha(
function,
a, &r, Policy())
||
!beta_detail::check_beta(
function,
b, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy())
||
!detail::check_probability(
function,
static_cast<value_type>(p),
&r,
Policy()))
return (RealType)r;
//
// Special cases first:
//
if(p == 0)
return comp
? 1.0f
: 0.0f;
if(p == 1)
return !comp
? 1.0f
: 0.0f;
value_type c = a + b + l / 2;
value_type mean = 1 - (b / c) * (1 + l / (2 * c * c));
/*
//
// Calculate a normal approximation to the quantile,
// uses mean and variance approximations from:
// Algorithm AS 310:
// Computing the Non-Central Beta Distribution Function
// R. Chattamvelli; R. Shanmugam
// Applied Statistics, Vol. 46, No. 1. (1997), pp. 146-156.
//
// Unfortunately, when this is wrong it tends to be *very*
// wrong, so it's disabled for now, even though it often
// gets the initial guess quite close. Probably we could
// do much better by factoring in the skewness if only
// we could calculate it....
//
value_type delta = l / 2;
value_type delta2 = delta * delta;
value_type delta3 = delta * delta2;
value_type delta4 = delta2 * delta2;
value_type G = c * (c + 1) + delta;
value_type alpha = a + b;
value_type alpha2 = alpha * alpha;
value_type eta = (2 * alpha + 1) * (2 * alpha + 1) + 1;
value_type H = 3 * alpha2 + 5 * alpha + 2;
value_type F = alpha2 * (alpha + 1) + H * delta
+ (2 * alpha + 4) * delta2 + delta3;
value_type P = (3 * alpha + 1) * (9 * alpha + 17)
+ 2 * alpha * (3 * alpha + 2) * (3 * alpha + 4) + 15;
value_type Q = 54 * alpha2 + 162 * alpha + 130;
value_type R = 6 * (6 * alpha + 11);
value_type D = delta
* (H * H + 2 * P * delta + Q * delta2 + R * delta3 + 9 * delta4);
value_type variance = (b / G)
* (1 + delta * (l * l + 3 * l + eta) / (G * G))
- (b * b / F) * (1 + D / (F * F));
value_type sd = sqrt(variance);
value_type guess = comp
? quantile(complement(normal_distribution<RealType, Policy>(static_cast<RealType>(mean), static_cast<RealType>(sd)), p))
: quantile(normal_distribution<RealType, Policy>(static_cast<RealType>(mean), static_cast<RealType>(sd)), p);
if(guess >= 1)
guess = mean;
if(guess <= tools::min_value<value_type>())
guess = mean;
*/
value_type guess = mean;
detail::nc_beta_quantile_functor<value_type, Policy>
f(non_central_beta_distribution<value_type, Policy>(a, b, l), p, comp);
tools::eps_tolerance<value_type> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
std::pair<value_type, value_type> ir
= bracket_and_solve_root_01(
f, guess, value_type(2.5), true, tol,
max_iter, Policy());
value_type result = ir.first + (ir.second - ir.first) / 2;
if(max_iter >= policies::get_max_root_iterations<Policy>())
{
return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
" either there is no answer to quantile of the non central beta distribution"
" or the answer is infinite. Current best guess is %1%",
policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
function), Policy());
}
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
function);
}
template <class T, class Policy>
T non_central_beta_pdf(T a, T b, T lam, T x, T y, const Policy& pol)
{
BOOST_MATH_STD_USING
//
// Special cases:
//
if((x == 0) || (y == 0))
return 0;
//
// Variables come first:
//
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T l2 = lam / 2;
//
// k is the starting point for iteration, and is the
// maximum of the poisson weighting term:
//
int k = itrunc(l2);
// Starting Poisson weight:
T pois = gamma_p_derivative(T(k+1), l2, pol);
// Starting beta term:
T beta = x < y ?
ibeta_derivative(a + k, b, x, pol)
: ibeta_derivative(b, a + k, y, pol);
T sum = 0;
T poisf(pois);
T betaf(beta);
//
// Stable backwards recursion first:
//
boost::uintmax_t count = k;
for(int i = k; i >= 0; --i)
{
T term = beta * pois;
sum += term;
if((fabs(term/sum) < errtol) || (term == 0))
{
count = k - i;
break;
}
pois *= i / l2;
beta *= (a + i - 1) / (x * (a + i + b - 1));
}
for(int i = k + 1; ; ++i)
{
poisf *= l2 / i;
betaf *= x * (a + b + i - 1) / (a + i - 1);
T term = poisf * betaf;
sum += term;
if((fabs(term/sum) < errtol) || (term == 0))
{
break;
}
if(static_cast<boost::uintmax_t>(count + i - k) > max_iter)
{
return policies::raise_evaluation_error(
"pdf(non_central_beta_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
}
}
return sum;
}
template <class RealType, class Policy>
RealType nc_beta_pdf(const non_central_beta_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING
static const char* function = "pdf(non_central_beta_distribution<%1%>, %1%)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
value_type a = dist.alpha();
value_type b = dist.beta();
value_type l = dist.non_centrality();
value_type r;
if(!beta_detail::check_alpha(
function,
a, &r, Policy())
||
!beta_detail::check_beta(
function,
b, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy())
||
!beta_detail::check_x(
function,
static_cast<value_type>(x),
&r,
Policy()))
return (RealType)r;
if(l == 0)
return pdf(boost::math::beta_distribution<RealType, Policy>(dist.alpha(), dist.beta()), x);
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
non_central_beta_pdf(a, b, l, static_cast<value_type>(x), value_type(1 - static_cast<value_type>(x)), forwarding_policy()),
"function");
}
template <class T>
struct hypergeometric_2F2_sum
{
typedef T result_type;
hypergeometric_2F2_sum(T a1_, T a2_, T b1_, T b2_, T z_) : a1(a1_), a2(a2_), b1(b1_), b2(b2_), z(z_), term(1), k(0) {}
T operator()()
{
T result = term;
term *= a1 * a2 / (b1 * b2);
a1 += 1;
a2 += 1;
b1 += 1;
b2 += 1;
k += 1;
term /= k;
term *= z;
return result;
}
T a1, a2, b1, b2, z, term, k;
};
template <class T, class Policy>
T hypergeometric_2F2(T a1, T a2, T b1, T b2, T z, const Policy& pol)
{
typedef typename policies::evaluation<T, Policy>::type value_type;
const char* function = "boost::math::detail::hypergeometric_2F2<%1%>(%1%,%1%,%1%,%1%,%1%)";
hypergeometric_2F2_sum<value_type> s(a1, a2, b1, b2, z);
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
value_type zero = 0;
value_type result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<value_type, Policy>(), max_iter, zero);
#else
value_type result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<value_type, Policy>(), max_iter);
#endif
policies::check_series_iterations<T>(function, max_iter, pol);
return policies::checked_narrowing_cast<T, Policy>(result, function);
}
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class non_central_beta_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
non_central_beta_distribution(RealType a_, RealType b_, RealType lambda) : a(a_), b(b_), ncp(lambda)
{
const char* function = "boost::math::non_central_beta_distribution<%1%>::non_central_beta_distribution(%1%,%1%)";
RealType r;
beta_detail::check_alpha(
function,
a, &r, Policy());
beta_detail::check_beta(
function,
b, &r, Policy());
detail::check_non_centrality(
function,
lambda,
&r,
Policy());
} // non_central_beta_distribution constructor.
RealType alpha() const
{ // Private data getter function.
return a;
}
RealType beta() const
{ // Private data getter function.
return b;
}
RealType non_centrality() const
{ // Private data getter function.
return ncp;
}
private:
// Data member, initialized by constructor.
RealType a; // alpha.
RealType b; // beta.
RealType ncp; // non-centrality parameter
}; // template <class RealType, class Policy> class non_central_beta_distribution
typedef non_central_beta_distribution<double> non_central_beta; // 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 non_central_beta_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), static_cast<RealType>(1));
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const non_central_beta_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>(static_cast<RealType>(0), static_cast<RealType>(1));
}
template <class RealType, class Policy>
inline RealType mode(const non_central_beta_distribution<RealType, Policy>& dist)
{ // mode.
static const char* function = "mode(non_central_beta_distribution<%1%> const&)";
RealType a = dist.alpha();
RealType b = dist.beta();
RealType l = dist.non_centrality();
RealType r;
if(!beta_detail::check_alpha(
function,
a, &r, Policy())
||
!beta_detail::check_beta(
function,
b, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy()))
return (RealType)r;
RealType c = a + b + l / 2;
RealType mean = 1 - (b / c) * (1 + l / (2 * c * c));
return detail::generic_find_mode_01(
dist,
mean,
function);
}
//
// We don't have the necessary information to implement
// these at present. These are just disabled for now,
// prototypes retained so we can fill in the blanks
// later:
//
template <class RealType, class Policy>
inline RealType mean(const non_central_beta_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING
RealType a = dist.alpha();
RealType b = dist.beta();
RealType d = dist.non_centrality();
RealType apb = a + b;
return exp(-d / 2) * a * detail::hypergeometric_2F2<RealType, Policy>(1 + a, apb, a, 1 + apb, d / 2, Policy()) / apb;
} // mean
template <class RealType, class Policy>
inline RealType variance(const non_central_beta_distribution<RealType, Policy>& dist)
{
//
// Relative error of this function may be arbitarily large... absolute
// error will be small however... that's the best we can do for now.
//
BOOST_MATH_STD_USING
RealType a = dist.alpha();
RealType b = dist.beta();
RealType d = dist.non_centrality();
RealType apb = a + b;
RealType result = detail::hypergeometric_2F2(RealType(1 + a), apb, a, RealType(1 + apb), RealType(d / 2), Policy());
result *= result * -exp(-d) * a * a / (apb * apb);
result += exp(-d / 2) * a * (1 + a) * detail::hypergeometric_2F2(RealType(2 + a), apb, a, RealType(2 + apb), RealType(d / 2), Policy()) / (apb * (1 + apb));
return result;
}
// RealType standard_deviation(const non_central_beta_distribution<RealType, Policy>& dist)
// standard_deviation provided by derived accessors.
template <class RealType, class Policy>
inline RealType skewness(const non_central_beta_distribution<RealType, Policy>& /*dist*/)
{ // skewness = sqrt(l).
const char* function = "boost::math::non_central_beta_distribution<%1%>::skewness()";
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
return policies::raise_evaluation_error<RealType>(
function,
"This function is not yet implemented, the only sensible result is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy()); // infinity?
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const non_central_beta_distribution<RealType, Policy>& /*dist*/)
{
const char* function = "boost::math::non_central_beta_distribution<%1%>::kurtosis_excess()";
typedef typename Policy::assert_undefined_type assert_type;
BOOST_STATIC_ASSERT(assert_type::value == 0);
return policies::raise_evaluation_error<RealType>(
function,
"This function is not yet implemented, the only sensible result is %1%.",
std::numeric_limits<RealType>::quiet_NaN(), Policy()); // infinity?
} // kurtosis_excess
template <class RealType, class Policy>
inline RealType kurtosis(const non_central_beta_distribution<RealType, Policy>& dist)
{
return kurtosis_excess(dist) + 3;
}
template <class RealType, class Policy>
inline RealType pdf(const non_central_beta_distribution<RealType, Policy>& dist, const RealType& x)
{ // Probability Density/Mass Function.
return detail::nc_beta_pdf(dist, x);
} // pdf
template <class RealType, class Policy>
RealType cdf(const non_central_beta_distribution<RealType, Policy>& dist, const RealType& x)
{
const char* function = "boost::math::non_central_beta_distribution<%1%>::cdf(%1%)";
RealType a = dist.alpha();
RealType b = dist.beta();
RealType l = dist.non_centrality();
RealType r;
if(!beta_detail::check_alpha(
function,
a, &r, Policy())
||
!beta_detail::check_beta(
function,
b, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy())
||
!beta_detail::check_x(
function,
x,
&r,
Policy()))
return (RealType)r;
if(l == 0)
return cdf(beta_distribution<RealType, Policy>(a, b), x);
return detail::non_central_beta_cdf(x, RealType(1 - x), a, b, l, false, Policy());
} // cdf
template <class RealType, class Policy>
RealType cdf(const complemented2_type<non_central_beta_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function
const char* function = "boost::math::non_central_beta_distribution<%1%>::cdf(%1%)";
non_central_beta_distribution<RealType, Policy> const& dist = c.dist;
RealType a = dist.alpha();
RealType b = dist.beta();
RealType l = dist.non_centrality();
RealType x = c.param;
RealType r;
if(!beta_detail::check_alpha(
function,
a, &r, Policy())
||
!beta_detail::check_beta(
function,
b, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy())
||
!beta_detail::check_x(
function,
x,
&r,
Policy()))
return (RealType)r;
if(l == 0)
return cdf(complement(beta_distribution<RealType, Policy>(a, b), x));
return detail::non_central_beta_cdf(x, RealType(1 - x), a, b, l, true, Policy());
} // ccdf
template <class RealType, class Policy>
inline RealType quantile(const non_central_beta_distribution<RealType, Policy>& dist, const RealType& p)
{ // Quantile (or Percent Point) function.
return detail::nc_beta_quantile(dist, p, false);
} // quantile
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<non_central_beta_distribution<RealType, Policy>, RealType>& c)
{ // Quantile (or Percent Point) function.
return detail::nc_beta_quantile(c.dist, c.param, true);
} // 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>
#endif // BOOST_MATH_SPECIAL_NON_CENTRAL_BETA_HPP

View File

@@ -0,0 +1,999 @@
// boost\math\distributions\non_central_chi_squared.hpp
// Copyright John Maddock 2008.
// 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_SPECIAL_NON_CENTRAL_CHI_SQUARE_HPP
#define BOOST_MATH_SPECIAL_NON_CENTRAL_CHI_SQUARE_HPP
#include <boost/math/distributions/fwd.hpp>
#include <boost/math/special_functions/gamma.hpp> // for incomplete gamma. gamma_q
#include <boost/math/special_functions/bessel.hpp> // for cyl_bessel_i
#include <boost/math/special_functions/round.hpp> // for iround
#include <boost/math/distributions/complement.hpp> // complements
#include <boost/math/distributions/chi_squared.hpp> // central distribution
#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.
#include <boost/math/distributions/detail/generic_mode.hpp>
#include <boost/math/distributions/detail/generic_quantile.hpp>
namespace boost
{
namespace math
{
template <class RealType, class Policy>
class non_central_chi_squared_distribution;
namespace detail{
template <class T, class Policy>
T non_central_chi_square_q(T x, T f, T theta, const Policy& pol, T init_sum = 0)
{
//
// Computes the complement of the Non-Central Chi-Square
// Distribution CDF by summing a weighted sum of complements
// of the central-distributions. The weighting factor is
// a Poisson Distribution.
//
// This is an application of the technique described in:
//
// Computing discrete mixtures of continuous
// distributions: noncentral chisquare, noncentral t
// and the distribution of the square of the sample
// multiple correlation coeficient.
// D. Benton, K. Krishnamoorthy.
// Computational Statistics & Data Analysis 43 (2003) 249 - 267
//
BOOST_MATH_STD_USING
// Special case:
if(x == 0)
return 1;
//
// Initialize the variables we'll be using:
//
T lambda = theta / 2;
T del = f / 2;
T y = x / 2;
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T sum = init_sum;
//
// k is the starting location for iteration, we'll
// move both forwards and backwards from this point.
// k is chosen as the peek of the Poisson weights, which
// will occur *before* the largest term.
//
int k = iround(lambda, pol);
// Forwards and backwards Poisson weights:
T poisf = boost::math::gamma_p_derivative(static_cast<T>(1 + k), lambda, pol);
T poisb = poisf * k / lambda;
// Initial forwards central chi squared term:
T gamf = boost::math::gamma_q(del + k, y, pol);
// Forwards and backwards recursion terms on the central chi squared:
T xtermf = boost::math::gamma_p_derivative(del + 1 + k, y, pol);
T xtermb = xtermf * (del + k) / y;
// Initial backwards central chi squared term:
T gamb = gamf - xtermb;
//
// Forwards iteration first, this is the
// stable direction for the gamma function
// recurrences:
//
int i;
for(i = k; static_cast<boost::uintmax_t>(i-k) < max_iter; ++i)
{
T term = poisf * gamf;
sum += term;
poisf *= lambda / (i + 1);
gamf += xtermf;
xtermf *= y / (del + i + 1);
if(((sum == 0) || (fabs(term / sum) < errtol)) && (term >= poisf * gamf))
break;
}
//Error check:
if(static_cast<boost::uintmax_t>(i-k) >= max_iter)
return policies::raise_evaluation_error(
"cdf(non_central_chi_squared_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
//
// Now backwards iteration: the gamma
// function recurrences are unstable in this
// direction, we rely on the terms deminishing in size
// faster than we introduce cancellation errors.
// For this reason it's very important that we start
// *before* the largest term so that backwards iteration
// is strictly converging.
//
for(i = k - 1; i >= 0; --i)
{
T term = poisb * gamb;
sum += term;
poisb *= i / lambda;
xtermb *= (del + i) / y;
gamb -= xtermb;
if((sum == 0) || (fabs(term / sum) < errtol))
break;
}
return sum;
}
template <class T, class Policy>
T non_central_chi_square_p_ding(T x, T f, T theta, const Policy& pol, T init_sum = 0)
{
//
// This is an implementation of:
//
// Algorithm AS 275:
// Computing the Non-Central #2 Distribution Function
// Cherng G. Ding
// Applied Statistics, Vol. 41, No. 2. (1992), pp. 478-482.
//
// This uses a stable forward iteration to sum the
// CDF, unfortunately this can not be used for large
// values of the non-centrality parameter because:
// * The first term may underfow to zero.
// * We may need an extra-ordinary number of terms
// before we reach the first *significant* term.
//
BOOST_MATH_STD_USING
// Special case:
if(x == 0)
return 0;
T tk = boost::math::gamma_p_derivative(f/2 + 1, x/2, pol);
T lambda = theta / 2;
T vk = exp(-lambda);
T uk = vk;
T sum = init_sum + tk * vk;
if(sum == 0)
return sum;
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
int i;
T lterm(0), term(0);
for(i = 1; static_cast<boost::uintmax_t>(i) < max_iter; ++i)
{
tk = tk * x / (f + 2 * i);
uk = uk * lambda / i;
vk = vk + uk;
lterm = term;
term = vk * tk;
sum += term;
if((fabs(term / sum) < errtol) && (term <= lterm))
break;
}
//Error check:
if(static_cast<boost::uintmax_t>(i) >= max_iter)
return policies::raise_evaluation_error(
"cdf(non_central_chi_squared_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
return sum;
}
template <class T, class Policy>
T non_central_chi_square_p(T y, T n, T lambda, const Policy& pol, T init_sum)
{
//
// This is taken more or less directly from:
//
// Computing discrete mixtures of continuous
// distributions: noncentral chisquare, noncentral t
// and the distribution of the square of the sample
// multiple correlation coeficient.
// D. Benton, K. Krishnamoorthy.
// Computational Statistics & Data Analysis 43 (2003) 249 - 267
//
// We're summing a Poisson weighting term multiplied by
// a central chi squared distribution.
//
BOOST_MATH_STD_USING
// Special case:
if(y == 0)
return 0;
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T errorf(0), errorb(0);
T x = y / 2;
T del = lambda / 2;
//
// Starting location for the iteration, we'll iterate
// both forwards and backwards from this point. The
// location chosen is the maximum of the Poisson weight
// function, which ocurrs *after* the largest term in the
// sum.
//
int k = iround(del, pol);
T a = n / 2 + k;
// Central chi squared term for forward iteration:
T gamkf = boost::math::gamma_p(a, x, pol);
if(lambda == 0)
return gamkf;
// Central chi squared term for backward iteration:
T gamkb = gamkf;
// Forwards Poisson weight:
T poiskf = gamma_p_derivative(static_cast<T>(k+1), del, pol);
// Backwards Poisson weight:
T poiskb = poiskf;
// Forwards gamma function recursion term:
T xtermf = boost::math::gamma_p_derivative(a, x, pol);
// Backwards gamma function recursion term:
T xtermb = xtermf * x / a;
T sum = init_sum + poiskf * gamkf;
if(sum == 0)
return sum;
int i = 1;
//
// Backwards recursion first, this is the stable
// direction for gamma function recurrences:
//
while(i <= k)
{
xtermb *= (a - i + 1) / x;
gamkb += xtermb;
poiskb = poiskb * (k - i + 1) / del;
errorf = errorb;
errorb = gamkb * poiskb;
sum += errorb;
if((fabs(errorb / sum) < errtol) && (errorb <= errorf))
break;
++i;
}
i = 1;
//
// Now forwards recursion, the gamma function
// recurrence relation is unstable in this direction,
// so we rely on the magnitude of successive terms
// decreasing faster than we introduce cancellation error.
// For this reason it's vital that k is chosen to be *after*
// the largest term, so that successive forward iterations
// are strictly (and rapidly) converging.
//
do
{
xtermf = xtermf * x / (a + i - 1);
gamkf = gamkf - xtermf;
poiskf = poiskf * del / (k + i);
errorf = poiskf * gamkf;
sum += errorf;
++i;
}while((fabs(errorf / sum) > errtol) && (static_cast<boost::uintmax_t>(i) < max_iter));
//Error check:
if(static_cast<boost::uintmax_t>(i) >= max_iter)
return policies::raise_evaluation_error(
"cdf(non_central_chi_squared_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
return sum;
}
template <class T, class Policy>
T non_central_chi_square_pdf(T x, T n, T lambda, const Policy& pol)
{
//
// As above but for the PDF:
//
BOOST_MATH_STD_USING
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
T errtol = boost::math::policies::get_epsilon<T, Policy>();
T x2 = x / 2;
T n2 = n / 2;
T l2 = lambda / 2;
T sum = 0;
int k = itrunc(l2);
T pois = gamma_p_derivative(static_cast<T>(k + 1), l2, pol) * gamma_p_derivative(static_cast<T>(n2 + k), x2);
if(pois == 0)
return 0;
T poisb = pois;
for(int i = k; ; ++i)
{
sum += pois;
if(pois / sum < errtol)
break;
if(static_cast<boost::uintmax_t>(i - k) >= max_iter)
return policies::raise_evaluation_error(
"pdf(non_central_chi_squared_distribution<%1%>, %1%)",
"Series did not converge, closest value was %1%", sum, pol);
pois *= l2 * x2 / ((i + 1) * (n2 + i));
}
for(int i = k - 1; i >= 0; --i)
{
poisb *= (i + 1) * (n2 + i) / (l2 * x2);
sum += poisb;
if(poisb / sum < errtol)
break;
}
return sum / 2;
}
template <class RealType, class Policy>
inline RealType non_central_chi_squared_cdf(RealType x, RealType k, RealType l, bool invert, const Policy&)
{
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
BOOST_MATH_STD_USING
value_type result;
if(l == 0)
return invert == false ? cdf(boost::math::chi_squared_distribution<RealType, Policy>(k), x) : cdf(complement(boost::math::chi_squared_distribution<RealType, Policy>(k), x));
else if(x > k + l)
{
// Complement is the smaller of the two:
result = detail::non_central_chi_square_q(
static_cast<value_type>(x),
static_cast<value_type>(k),
static_cast<value_type>(l),
forwarding_policy(),
static_cast<value_type>(invert ? 0 : -1));
invert = !invert;
}
else if(l < 200)
{
// For small values of the non-centrality parameter
// we can use Ding's method:
result = detail::non_central_chi_square_p_ding(
static_cast<value_type>(x),
static_cast<value_type>(k),
static_cast<value_type>(l),
forwarding_policy(),
static_cast<value_type>(invert ? -1 : 0));
}
else
{
// For largers values of the non-centrality
// parameter Ding's method will consume an
// extra-ordinary number of terms, and worse
// may return zero when the result is in fact
// finite, use Krishnamoorthy's method instead:
result = detail::non_central_chi_square_p(
static_cast<value_type>(x),
static_cast<value_type>(k),
static_cast<value_type>(l),
forwarding_policy(),
static_cast<value_type>(invert ? -1 : 0));
}
if(invert)
result = -result;
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
"boost::math::non_central_chi_squared_cdf<%1%>(%1%, %1%, %1%)");
}
template <class T, class Policy>
struct nccs_quantile_functor
{
nccs_quantile_functor(const non_central_chi_squared_distribution<T,Policy>& d, T t, bool c)
: dist(d), target(t), comp(c) {}
T operator()(const T& x)
{
return comp ?
target - cdf(complement(dist, x))
: cdf(dist, x) - target;
}
private:
non_central_chi_squared_distribution<T,Policy> dist;
T target;
bool comp;
};
template <class RealType, class Policy>
RealType nccs_quantile(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& p, bool comp)
{
BOOST_MATH_STD_USING
static const char* function = "quantile(non_central_chi_squared_distribution<%1%>, %1%)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
value_type k = dist.degrees_of_freedom();
value_type l = dist.non_centrality();
value_type r;
if(!detail::check_df(
function,
k, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy())
||
!detail::check_probability(
function,
static_cast<value_type>(p),
&r,
Policy()))
return (RealType)r;
//
// Special cases get short-circuited first:
//
if(p == 0)
return comp ? policies::raise_overflow_error<RealType>(function, 0, Policy()) : 0;
if(p == 1)
return comp ? 0 : policies::raise_overflow_error<RealType>(function, 0, Policy());
//
// This is Pearson's approximation to the quantile, see
// Pearson, E. S. (1959) "Note on an approximation to the distribution of
// noncentral chi squared", Biometrika 46: 364.
// See also:
// "A comparison of approximations to percentiles of the noncentral chi2-distribution",
// Hardeo Sahai and Mario Miguel Ojeda, Revista de Matematica: Teoria y Aplicaciones 2003 10(1-2) : 57-76.
// Note that the latter reference refers to an approximation of the CDF, when they really mean the quantile.
//
value_type b = -(l * l) / (k + 3 * l);
value_type c = (k + 3 * l) / (k + 2 * l);
value_type ff = (k + 2 * l) / (c * c);
value_type guess;
if(comp)
{
guess = b + c * quantile(complement(chi_squared_distribution<value_type, forwarding_policy>(ff), p));
}
else
{
guess = b + c * quantile(chi_squared_distribution<value_type, forwarding_policy>(ff), p);
}
//
// Sometimes guess goes very small or negative, in that case we have
// to do something else for the initial guess, this approximation
// was provided in a private communication from Thomas Luu, PhD candidate,
// University College London. It's an asymptotic expansion for the
// quantile which usually gets us within an order of magnitude of the
// correct answer.
// Fast and accurate parallel computation of quantile functions for random number generation,
// Thomas LuuDoctorial Thesis 2016
// http://discovery.ucl.ac.uk/1482128/
//
if(guess < 0.005)
{
value_type pp = comp ? 1 - p : p;
//guess = pow(pow(value_type(2), (k / 2 - 1)) * exp(l / 2) * pp * k, 2 / k);
guess = pow(pow(value_type(2), (k / 2 - 1)) * exp(l / 2) * pp * k * boost::math::tgamma(k / 2, forwarding_policy()), (2 / k));
if(guess == 0)
guess = tools::min_value<value_type>();
}
value_type result = detail::generic_quantile(
non_central_chi_squared_distribution<value_type, forwarding_policy>(k, l),
p,
guess,
comp,
function);
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
function);
}
template <class RealType, class Policy>
RealType nccs_pdf(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
{
BOOST_MATH_STD_USING
static const char* function = "pdf(non_central_chi_squared_distribution<%1%>, %1%)";
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
value_type k = dist.degrees_of_freedom();
value_type l = dist.non_centrality();
value_type r;
if(!detail::check_df(
function,
k, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy())
||
!detail::check_positive_x(
function,
(value_type)x,
&r,
Policy()))
return (RealType)r;
if(l == 0)
return pdf(boost::math::chi_squared_distribution<RealType, forwarding_policy>(dist.degrees_of_freedom()), x);
// Special case:
if(x == 0)
return 0;
if(l > 50)
{
r = non_central_chi_square_pdf(static_cast<value_type>(x), k, l, forwarding_policy());
}
else
{
r = log(x / l) * (k / 4 - 0.5f) - (x + l) / 2;
if(fabs(r) >= tools::log_max_value<RealType>() / 4)
{
r = non_central_chi_square_pdf(static_cast<value_type>(x), k, l, forwarding_policy());
}
else
{
r = exp(r);
r = 0.5f * r
* boost::math::cyl_bessel_i(k/2 - 1, sqrt(l * x), forwarding_policy());
}
}
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
r,
function);
}
template <class RealType, class Policy>
struct degrees_of_freedom_finder
{
degrees_of_freedom_finder(
RealType lam_, RealType x_, RealType p_, bool c)
: lam(lam_), x(x_), p(p_), comp(c) {}
RealType operator()(const RealType& v)
{
non_central_chi_squared_distribution<RealType, Policy> d(v, lam);
return comp ?
RealType(p - cdf(complement(d, x)))
: RealType(cdf(d, x) - p);
}
private:
RealType lam;
RealType x;
RealType p;
bool comp;
};
template <class RealType, class Policy>
inline RealType find_degrees_of_freedom(
RealType lam, RealType x, RealType p, RealType q, const Policy& pol)
{
const char* function = "non_central_chi_squared<%1%>::find_degrees_of_freedom";
if((p == 0) || (q == 0))
{
//
// Can't a thing if one of p and q is zero:
//
return policies::raise_evaluation_error<RealType>(function,
"Can't find degrees of freedom when the probability is 0 or 1, only possible answer is %1%",
RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
}
degrees_of_freedom_finder<RealType, Policy> f(lam, x, p < q ? p : q, p < q ? false : true);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
//
// Pick an initial guess that we know will give us a probability
// right around 0.5.
//
RealType guess = x - lam;
if(guess < 1)
guess = 1;
std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
f, guess, RealType(2), false, tol, max_iter, pol);
RealType result = ir.first + (ir.second - ir.first) / 2;
if(max_iter >= policies::get_max_root_iterations<Policy>())
{
return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
" or there is no answer to problem. Current best guess is %1%", result, Policy());
}
return result;
}
template <class RealType, class Policy>
struct non_centrality_finder
{
non_centrality_finder(
RealType v_, RealType x_, RealType p_, bool c)
: v(v_), x(x_), p(p_), comp(c) {}
RealType operator()(const RealType& lam)
{
non_central_chi_squared_distribution<RealType, Policy> d(v, lam);
return comp ?
RealType(p - cdf(complement(d, x)))
: RealType(cdf(d, x) - p);
}
private:
RealType v;
RealType x;
RealType p;
bool comp;
};
template <class RealType, class Policy>
inline RealType find_non_centrality(
RealType v, RealType x, RealType p, RealType q, const Policy& pol)
{
const char* function = "non_central_chi_squared<%1%>::find_non_centrality";
if((p == 0) || (q == 0))
{
//
// Can't do a thing if one of p and q is zero:
//
return policies::raise_evaluation_error<RealType>(function,
"Can't find non centrality parameter when the probability is 0 or 1, only possible answer is %1%",
RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
}
non_centrality_finder<RealType, Policy> f(v, x, p < q ? p : q, p < q ? false : true);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
//
// Pick an initial guess that we know will give us a probability
// right around 0.5.
//
RealType guess = x - v;
if(guess < 1)
guess = 1;
std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
f, guess, RealType(2), false, tol, max_iter, pol);
RealType result = ir.first + (ir.second - ir.first) / 2;
if(max_iter >= policies::get_max_root_iterations<Policy>())
{
return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
" or there is no answer to problem. Current best guess is %1%", result, Policy());
}
return result;
}
}
template <class RealType = double, class Policy = policies::policy<> >
class non_central_chi_squared_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
non_central_chi_squared_distribution(RealType df_, RealType lambda) : df(df_), ncp(lambda)
{
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::non_central_chi_squared_distribution(%1%,%1%)";
RealType r;
detail::check_df(
function,
df, &r, Policy());
detail::check_non_centrality(
function,
ncp,
&r,
Policy());
} // non_central_chi_squared_distribution constructor.
RealType degrees_of_freedom() const
{ // Private data getter function.
return df;
}
RealType non_centrality() const
{ // Private data getter function.
return ncp;
}
static RealType find_degrees_of_freedom(RealType lam, RealType x, RealType p)
{
const char* function = "non_central_chi_squared<%1%>::find_degrees_of_freedom";
typedef typename policies::evaluation<RealType, Policy>::type eval_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
eval_type result = detail::find_degrees_of_freedom(
static_cast<eval_type>(lam),
static_cast<eval_type>(x),
static_cast<eval_type>(p),
static_cast<eval_type>(1-p),
forwarding_policy());
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
function);
}
template <class A, class B, class C>
static RealType find_degrees_of_freedom(const complemented3_type<A,B,C>& c)
{
const char* function = "non_central_chi_squared<%1%>::find_degrees_of_freedom";
typedef typename policies::evaluation<RealType, Policy>::type eval_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
eval_type result = detail::find_degrees_of_freedom(
static_cast<eval_type>(c.dist),
static_cast<eval_type>(c.param1),
static_cast<eval_type>(1-c.param2),
static_cast<eval_type>(c.param2),
forwarding_policy());
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
function);
}
static RealType find_non_centrality(RealType v, RealType x, RealType p)
{
const char* function = "non_central_chi_squared<%1%>::find_non_centrality";
typedef typename policies::evaluation<RealType, Policy>::type eval_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
eval_type result = detail::find_non_centrality(
static_cast<eval_type>(v),
static_cast<eval_type>(x),
static_cast<eval_type>(p),
static_cast<eval_type>(1-p),
forwarding_policy());
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
function);
}
template <class A, class B, class C>
static RealType find_non_centrality(const complemented3_type<A,B,C>& c)
{
const char* function = "non_central_chi_squared<%1%>::find_non_centrality";
typedef typename policies::evaluation<RealType, Policy>::type eval_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
eval_type result = detail::find_non_centrality(
static_cast<eval_type>(c.dist),
static_cast<eval_type>(c.param1),
static_cast<eval_type>(1-c.param2),
static_cast<eval_type>(c.param2),
forwarding_policy());
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
result,
function);
}
private:
// Data member, initialized by constructor.
RealType df; // degrees of freedom.
RealType ncp; // non-centrality parameter
}; // template <class RealType, class Policy> class non_central_chi_squared_distribution
typedef non_central_chi_squared_distribution<double> non_central_chi_squared; // 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 non_central_chi_squared_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), max_value<RealType>()); // Max integer?
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const non_central_chi_squared_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>(static_cast<RealType>(0), max_value<RealType>());
}
template <class RealType, class Policy>
inline RealType mean(const non_central_chi_squared_distribution<RealType, Policy>& dist)
{ // Mean of poisson distribution = lambda.
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::mean()";
RealType k = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
if(!detail::check_df(
function,
k, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy()))
return r;
return k + l;
} // mean
template <class RealType, class Policy>
inline RealType mode(const non_central_chi_squared_distribution<RealType, Policy>& dist)
{ // mode.
static const char* function = "mode(non_central_chi_squared_distribution<%1%> const&)";
RealType k = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
if(!detail::check_df(
function,
k, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy()))
return (RealType)r;
return detail::generic_find_mode(dist, 1 + k, function);
}
template <class RealType, class Policy>
inline RealType variance(const non_central_chi_squared_distribution<RealType, Policy>& dist)
{ // variance.
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::variance()";
RealType k = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
if(!detail::check_df(
function,
k, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy()))
return r;
return 2 * (2 * l + k);
}
// RealType standard_deviation(const non_central_chi_squared_distribution<RealType, Policy>& dist)
// standard_deviation provided by derived accessors.
template <class RealType, class Policy>
inline RealType skewness(const non_central_chi_squared_distribution<RealType, Policy>& dist)
{ // skewness = sqrt(l).
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::skewness()";
RealType k = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
if(!detail::check_df(
function,
k, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy()))
return r;
BOOST_MATH_STD_USING
return pow(2 / (k + 2 * l), RealType(3)/2) * (k + 3 * l);
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const non_central_chi_squared_distribution<RealType, Policy>& dist)
{
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::kurtosis_excess()";
RealType k = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
if(!detail::check_df(
function,
k, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy()))
return r;
return 12 * (k + 4 * l) / ((k + 2 * l) * (k + 2 * l));
} // kurtosis_excess
template <class RealType, class Policy>
inline RealType kurtosis(const non_central_chi_squared_distribution<RealType, Policy>& dist)
{
return kurtosis_excess(dist) + 3;
}
template <class RealType, class Policy>
inline RealType pdf(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
{ // Probability Density/Mass Function.
return detail::nccs_pdf(dist, x);
} // pdf
template <class RealType, class Policy>
RealType cdf(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
{
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::cdf(%1%)";
RealType k = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
if(!detail::check_df(
function,
k, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy())
||
!detail::check_positive_x(
function,
x,
&r,
Policy()))
return r;
return detail::non_central_chi_squared_cdf(x, k, l, false, Policy());
} // cdf
template <class RealType, class Policy>
RealType cdf(const complemented2_type<non_central_chi_squared_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::cdf(%1%)";
non_central_chi_squared_distribution<RealType, Policy> const& dist = c.dist;
RealType x = c.param;
RealType k = dist.degrees_of_freedom();
RealType l = dist.non_centrality();
RealType r;
if(!detail::check_df(
function,
k, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy())
||
!detail::check_positive_x(
function,
x,
&r,
Policy()))
return r;
return detail::non_central_chi_squared_cdf(x, k, l, true, Policy());
} // ccdf
template <class RealType, class Policy>
inline RealType quantile(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& p)
{ // Quantile (or Percent Point) function.
return detail::nccs_quantile(dist, p, false);
} // quantile
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<non_central_chi_squared_distribution<RealType, Policy>, RealType>& c)
{ // Quantile (or Percent Point) function.
return detail::nccs_quantile(c.dist, c.param, true);
} // 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>
#endif // BOOST_MATH_SPECIAL_NON_CENTRAL_CHI_SQUARE_HPP

View File

@@ -0,0 +1,410 @@
// boost\math\distributions\non_central_f.hpp
// Copyright John Maddock 2008.
// 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_SPECIAL_NON_CENTRAL_F_HPP
#define BOOST_MATH_SPECIAL_NON_CENTRAL_F_HPP
#include <boost/math/distributions/non_central_beta.hpp>
#include <boost/math/distributions/detail/generic_mode.hpp>
#include <boost/math/special_functions/pow.hpp>
namespace boost
{
namespace math
{
template <class RealType = double, class Policy = policies::policy<> >
class non_central_f_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
non_central_f_distribution(RealType v1_, RealType v2_, RealType lambda) : v1(v1_), v2(v2_), ncp(lambda)
{
const char* function = "boost::math::non_central_f_distribution<%1%>::non_central_f_distribution(%1%,%1%)";
RealType r;
detail::check_df(
function,
v1, &r, Policy());
detail::check_df(
function,
v2, &r, Policy());
detail::check_non_centrality(
function,
lambda,
&r,
Policy());
} // non_central_f_distribution constructor.
RealType degrees_of_freedom1()const
{
return v1;
}
RealType degrees_of_freedom2()const
{
return v2;
}
RealType non_centrality() const
{ // Private data getter function.
return ncp;
}
private:
// Data member, initialized by constructor.
RealType v1; // alpha.
RealType v2; // beta.
RealType ncp; // non-centrality parameter
}; // template <class RealType, class Policy> class non_central_f_distribution
typedef non_central_f_distribution<double> non_central_f; // 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 non_central_f_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), max_value<RealType>());
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const non_central_f_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>(static_cast<RealType>(0), max_value<RealType>());
}
template <class RealType, class Policy>
inline RealType mean(const non_central_f_distribution<RealType, Policy>& dist)
{
const char* function = "mean(non_central_f_distribution<%1%> const&)";
RealType v1 = dist.degrees_of_freedom1();
RealType v2 = dist.degrees_of_freedom2();
RealType l = dist.non_centrality();
RealType r;
if(!detail::check_df(
function,
v1, &r, Policy())
||
!detail::check_df(
function,
v2, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy()))
return r;
if(v2 <= 2)
return policies::raise_domain_error(
function,
"Second degrees of freedom parameter was %1%, but must be > 2 !",
v2, Policy());
return v2 * (v1 + l) / (v1 * (v2 - 2));
} // mean
template <class RealType, class Policy>
inline RealType mode(const non_central_f_distribution<RealType, Policy>& dist)
{ // mode.
static const char* function = "mode(non_central_chi_squared_distribution<%1%> const&)";
RealType n = dist.degrees_of_freedom1();
RealType m = dist.degrees_of_freedom2();
RealType l = dist.non_centrality();
RealType r;
if(!detail::check_df(
function,
n, &r, Policy())
||
!detail::check_df(
function,
m, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy()))
return r;
RealType guess = m > 2 ? RealType(m * (n + l) / (n * (m - 2))) : RealType(1);
return detail::generic_find_mode(
dist,
guess,
function);
}
template <class RealType, class Policy>
inline RealType variance(const non_central_f_distribution<RealType, Policy>& dist)
{ // variance.
const char* function = "variance(non_central_f_distribution<%1%> const&)";
RealType n = dist.degrees_of_freedom1();
RealType m = dist.degrees_of_freedom2();
RealType l = dist.non_centrality();
RealType r;
if(!detail::check_df(
function,
n, &r, Policy())
||
!detail::check_df(
function,
m, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy()))
return r;
if(m <= 4)
return policies::raise_domain_error(
function,
"Second degrees of freedom parameter was %1%, but must be > 4 !",
m, Policy());
RealType result = 2 * m * m * ((n + l) * (n + l)
+ (m - 2) * (n + 2 * l));
result /= (m - 4) * (m - 2) * (m - 2) * n * n;
return result;
}
// RealType standard_deviation(const non_central_f_distribution<RealType, Policy>& dist)
// standard_deviation provided by derived accessors.
template <class RealType, class Policy>
inline RealType skewness(const non_central_f_distribution<RealType, Policy>& dist)
{ // skewness = sqrt(l).
const char* function = "skewness(non_central_f_distribution<%1%> const&)";
BOOST_MATH_STD_USING
RealType n = dist.degrees_of_freedom1();
RealType m = dist.degrees_of_freedom2();
RealType l = dist.non_centrality();
RealType r;
if(!detail::check_df(
function,
n, &r, Policy())
||
!detail::check_df(
function,
m, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy()))
return r;
if(m <= 6)
return policies::raise_domain_error(
function,
"Second degrees of freedom parameter was %1%, but must be > 6 !",
m, Policy());
RealType result = 2 * constants::root_two<RealType>();
result *= sqrt(m - 4);
result *= (n * (m + n - 2) *(m + 2 * n - 2)
+ 3 * (m + n - 2) * (m + 2 * n - 2) * l
+ 6 * (m + n - 2) * l * l + 2 * l * l * l);
result /= (m - 6) * pow(n * (m + n - 2) + 2 * (m + n - 2) * l + l * l, RealType(1.5f));
return result;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const non_central_f_distribution<RealType, Policy>& dist)
{
const char* function = "kurtosis_excess(non_central_f_distribution<%1%> const&)";
BOOST_MATH_STD_USING
RealType n = dist.degrees_of_freedom1();
RealType m = dist.degrees_of_freedom2();
RealType l = dist.non_centrality();
RealType r;
if(!detail::check_df(
function,
n, &r, Policy())
||
!detail::check_df(
function,
m, &r, Policy())
||
!detail::check_non_centrality(
function,
l,
&r,
Policy()))
return r;
if(m <= 8)
return policies::raise_domain_error(
function,
"Second degrees of freedom parameter was %1%, but must be > 8 !",
m, Policy());
RealType l2 = l * l;
RealType l3 = l2 * l;
RealType l4 = l2 * l2;
RealType result = (3 * (m - 4) * (n * (m + n - 2)
* (4 * (m - 2) * (m - 2)
+ (m - 2) * (m + 10) * n
+ (10 + m) * n * n)
+ 4 * (m + n - 2) * (4 * (m - 2) * (m - 2)
+ (m - 2) * (10 + m) * n
+ (10 + m) * n * n) * l + 2 * (10 + m)
* (m + n - 2) * (2 * m + 3 * n - 4) * l2
+ 4 * (10 + m) * (-2 + m + n) * l3
+ (10 + m) * l4))
/
((-8 + m) * (-6 + m) * boost::math::pow<2>(n * (-2 + m + n)
+ 2 * (-2 + m + n) * l + l2));
return result;
} // kurtosis_excess
template <class RealType, class Policy>
inline RealType kurtosis(const non_central_f_distribution<RealType, Policy>& dist)
{
return kurtosis_excess(dist) + 3;
}
template <class RealType, class Policy>
inline RealType pdf(const non_central_f_distribution<RealType, Policy>& dist, const RealType& x)
{ // Probability Density/Mass Function.
typedef typename policies::evaluation<RealType, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
value_type alpha = dist.degrees_of_freedom1() / 2;
value_type beta = dist.degrees_of_freedom2() / 2;
value_type y = x * alpha / beta;
value_type r = pdf(boost::math::non_central_beta_distribution<value_type, forwarding_policy>(alpha, beta, dist.non_centrality()), y / (1 + y));
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
r * (dist.degrees_of_freedom1() / dist.degrees_of_freedom2()) / ((1 + y) * (1 + y)),
"pdf(non_central_f_distribution<%1%>, %1%)");
} // pdf
template <class RealType, class Policy>
RealType cdf(const non_central_f_distribution<RealType, Policy>& dist, const RealType& x)
{
const char* function = "cdf(const non_central_f_distribution<%1%>&, %1%)";
RealType r;
if(!detail::check_df(
function,
dist.degrees_of_freedom1(), &r, Policy())
||
!detail::check_df(
function,
dist.degrees_of_freedom2(), &r, Policy())
||
!detail::check_non_centrality(
function,
dist.non_centrality(),
&r,
Policy()))
return r;
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 alpha = dist.degrees_of_freedom1() / 2;
RealType beta = dist.degrees_of_freedom2() / 2;
RealType y = x * alpha / beta;
RealType c = y / (1 + y);
RealType cp = 1 / (1 + y);
//
// To ensure accuracy, we pass both x and 1-x to the
// non-central beta cdf routine, this ensures accuracy
// even when we compute x to be ~ 1:
//
r = detail::non_central_beta_cdf(c, cp, alpha, beta,
dist.non_centrality(), false, Policy());
return r;
} // cdf
template <class RealType, class Policy>
RealType cdf(const complemented2_type<non_central_f_distribution<RealType, Policy>, RealType>& c)
{ // Complemented Cumulative Distribution Function
const char* function = "cdf(complement(const non_central_f_distribution<%1%>&, %1%))";
RealType r;
if(!detail::check_df(
function,
c.dist.degrees_of_freedom1(), &r, Policy())
||
!detail::check_df(
function,
c.dist.degrees_of_freedom2(), &r, Policy())
||
!detail::check_non_centrality(
function,
c.dist.non_centrality(),
&r,
Policy()))
return r;
if((c.param < 0) || !(boost::math::isfinite)(c.param))
{
return policies::raise_domain_error<RealType>(
function, "Random Variable parameter was %1%, but must be > 0 !", c.param, Policy());
}
RealType alpha = c.dist.degrees_of_freedom1() / 2;
RealType beta = c.dist.degrees_of_freedom2() / 2;
RealType y = c.param * alpha / beta;
RealType x = y / (1 + y);
RealType cx = 1 / (1 + y);
//
// To ensure accuracy, we pass both x and 1-x to the
// non-central beta cdf routine, this ensures accuracy
// even when we compute x to be ~ 1:
//
r = detail::non_central_beta_cdf(x, cx, alpha, beta,
c.dist.non_centrality(), true, Policy());
return r;
} // ccdf
template <class RealType, class Policy>
inline RealType quantile(const non_central_f_distribution<RealType, Policy>& dist, const RealType& p)
{ // Quantile (or Percent Point) function.
RealType alpha = dist.degrees_of_freedom1() / 2;
RealType beta = dist.degrees_of_freedom2() / 2;
RealType x = quantile(boost::math::non_central_beta_distribution<RealType, Policy>(alpha, beta, dist.non_centrality()), p);
if(x == 1)
return policies::raise_overflow_error<RealType>(
"quantile(const non_central_f_distribution<%1%>&, %1%)",
"Result of non central F quantile is too large to represent.",
Policy());
return (x / (1 - x)) * (dist.degrees_of_freedom2() / dist.degrees_of_freedom1());
} // quantile
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<non_central_f_distribution<RealType, Policy>, RealType>& c)
{ // Quantile (or Percent Point) function.
RealType alpha = c.dist.degrees_of_freedom1() / 2;
RealType beta = c.dist.degrees_of_freedom2() / 2;
RealType x = quantile(complement(boost::math::non_central_beta_distribution<RealType, Policy>(alpha, beta, c.dist.non_centrality()), c.param));
if(x == 1)
return policies::raise_overflow_error<RealType>(
"quantile(complement(const non_central_f_distribution<%1%>&, %1%))",
"Result of non central F quantile is too large to represent.",
Policy());
return (x / (1 - x)) * (c.dist.degrees_of_freedom2() / c.dist.degrees_of_freedom1());
} // 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>
#endif // BOOST_MATH_SPECIAL_NON_CENTRAL_F_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,329 @@
// 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 l_mean = 0, RealType sd = 1)
: m_mean(l_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, l_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;
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127)
#endif
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.
if (std::numeric_limits<RealType>::has_infinity)
{
return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
}
else
{ // Can only use max_value.
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*/)
{ // This is range values for random variable x where cdf rises from 0 to 1, and outside it, the pdf is zero.
if (std::numeric_limits<RealType>::has_infinity)
{
return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
}
else
{ // Can only use max_value.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
}
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
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%)";
RealType result = 0;
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))
{
return 0; // pdf + and - infinity is zero.
}
// Below 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;
//}
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 = 0;
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 = 0;
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%)";
RealType result = 0;
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 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;
//}
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 = 0;
if(false == detail::check_scale(function, sd, &result, Policy()))
return result;
if(false == detail::check_location(function, mean, &result, Policy()))
return result;
RealType q = c.param;
if(false == detail::check_probability(function, q, &result, Policy()))
return result;
result = boost::math::erfc_inv(2 * q, Policy());
result *= sd * constants::root_two<RealType>();
result += mean;
return result;
} // quantile
template <class RealType, class Policy>
inline RealType mean(const normal_distribution<RealType, Policy>& dist)
{
return dist.mean();
}
template <class RealType, class Policy>
inline RealType standard_deviation(const normal_distribution<RealType, Policy>& dist)
{
return dist.standard_deviation();
}
template <class RealType, class Policy>
inline RealType mode(const normal_distribution<RealType, Policy>& dist)
{
return dist.mean();
}
template <class RealType, class Policy>
inline RealType median(const normal_distribution<RealType, Policy>& dist)
{
return dist.mean();
}
template <class RealType, class Policy>
inline RealType skewness(const normal_distribution<RealType, Policy>& /*dist*/)
{
return 0;
}
template <class RealType, class Policy>
inline RealType kurtosis(const normal_distribution<RealType, Policy>& /*dist*/)
{
return 3;
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const normal_distribution<RealType, Policy>& /*dist*/)
{
return 0;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_NORMAL_HPP

View File

@@ -0,0 +1,444 @@
// Copyright John Maddock 2007.
// Copyright Paul A. Bristow 2007, 2009
// 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
// Handbook of Statistical Distributions with Applications, K Krishnamoorthy, ISBN 1-58488-635-8, Chapter 23, pp 257 - 267.
// Caution KK's a and b are the reverse of Mathworld!
#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_scale(
const char* function,
RealType scale,
RealType* result, const Policy& pol)
{
if((boost::math::isfinite)(scale))
{ // any > 0 finite value is OK.
if (scale > 0)
{
return true;
}
else
{
*result = policies::raise_domain_error<RealType>(
function,
"Scale parameter is %1%, but must be > 0!", scale, pol);
return false;
}
}
else
{ // Not finite.
*result = policies::raise_domain_error<RealType>(
function,
"Scale parameter is %1%, but must be finite!", scale, pol);
return false;
}
} // bool check_pareto_scale
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 scale,
RealType shape,
RealType* result, const Policy& pol)
{
return check_pareto_scale(function, scale, 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 l_scale = 1, RealType l_shape = 1)
: m_scale(l_scale), m_shape(l_shape)
{ // Constructor.
RealType result = 0;
detail::check_pareto("boost::math::pareto_distribution<%1%>::pareto_distribution", l_scale, l_shape, &result, Policy());
}
RealType scale()const
{ // AKA Xm and Wolfram b and beta
return m_scale;
}
RealType shape()const
{ // AKA k and Wolfram a and alpha
return m_shape;
}
private:
// Data members:
RealType m_scale; // distribution scale (xm) or beta
RealType m_shape; // distribution shape (k) or alpha
};
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>(static_cast<RealType>(0), max_value<RealType>()); // scale 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.scale(), max_value<RealType>() ); // scale 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 scale = dist.scale();
RealType shape = dist.shape();
RealType result = 0;
if(false == (detail::check_pareto_x(function, x, &result, Policy())
&& detail::check_pareto(function, scale, shape, &result, Policy())))
return result;
if (x < scale)
{ // regardless of shape, pdf is zero (or should be disallow x < scale and throw an exception?).
return 0;
}
result = shape * pow(scale, 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 scale = dist.scale();
RealType shape = dist.shape();
RealType result = 0;
if(false == (detail::check_pareto_x(function, x, &result, Policy())
&& detail::check_pareto(function, scale, shape, &result, Policy())))
return result;
if (x <= scale)
{ // regardless of shape, cdf is zero.
return 0;
}
// result = RealType(1) - pow((scale / x), shape);
result = -boost::math::powm1(scale/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 = 0;
RealType scale = dist.scale();
RealType shape = dist.shape();
if(false == (detail::check_probability(function, p, &result, Policy())
&& detail::check_pareto(function, scale, shape, &result, Policy())))
{
return result;
}
if (p == 0)
{
return scale; // x must be scale (or less).
}
if (p == 1)
{
return policies::raise_overflow_error<RealType>(function, 0, Policy()); // x = + infinity.
}
result = scale /
(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 = 0;
RealType x = c.param;
RealType scale = c.dist.scale();
RealType shape = c.dist.shape();
if(false == (detail::check_pareto_x(function, x, &result, Policy())
&& detail::check_pareto(function, scale, shape, &result, Policy())))
return result;
if (x <= scale)
{ // regardless of shape, cdf is zero, and complement is unity.
return 1;
}
result = pow((scale/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 = 0;
RealType q = c.param;
RealType scale = c.dist.scale();
RealType shape = c.dist.shape();
if(false == (detail::check_probability(function, q, &result, Policy())
&& detail::check_pareto(function, scale, shape, &result, Policy())))
{
return result;
}
if (q == 1)
{
return scale; // x must be scale (or less).
}
if (q == 0)
{
return policies::raise_overflow_error<RealType>(function, 0, Policy()); // x = + infinity.
}
result = scale / (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 = 0;
static const char* function = "boost::math::mean(const pareto_distribution<%1%>&, %1%)";
if(false == detail::check_pareto(function, dist.scale(), dist.shape(), &result, Policy()))
{
return result;
}
if (dist.shape() > RealType(1))
{
return dist.shape() * dist.scale() / (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.scale();
} // mode
template <class RealType, class Policy>
inline RealType median(const pareto_distribution<RealType, Policy>& dist)
{
RealType result = 0;
static const char* function = "boost::math::median(const pareto_distribution<%1%>&, %1%)";
if(false == detail::check_pareto(function, dist.scale(), dist.shape(), &result, Policy()))
{
return result;
}
BOOST_MATH_STD_USING
return dist.scale() * pow(RealType(2), (1/dist.shape()));
} // median
template <class RealType, class Policy>
inline RealType variance(const pareto_distribution<RealType, Policy>& dist)
{
RealType result = 0;
RealType scale = dist.scale();
RealType shape = dist.shape();
static const char* function = "boost::math::variance(const pareto_distribution<%1%>&, %1%)";
if(false == detail::check_pareto(function, scale, shape, &result, Policy()))
{
return result;
}
if (shape > 2)
{
result = (scale * scale * 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 = 0;
RealType shape = dist.shape();
static const char* function = "boost::math::pdf(const pareto_distribution<%1%>&, %1%)";
if(false == detail::check_pareto(function, dist.scale(), 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 = 0;
RealType shape = dist.shape();
static const char* function = "boost::math::pdf(const pareto_distribution<%1%>&, %1%)";
if(false == detail::check_pareto(function, dist.scale(), 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 = 0;
RealType shape = dist.shape();
static const char* function = "boost::math::pdf(const pareto_distribution<%1%>&, %1%)";
if(false == detail::check_pareto(function, dist.scale(), shape, &result, Policy()))
{
return result;
}
if (shape > 4)
{
result = 6 * ((shape * shape * shape) + (shape * shape) - 6 * shape - 2) /
(shape * (shape - 3) * (shape - 4));
}
else
{
result = policies::raise_domain_error<RealType>(
function,
"kurtosis_excess is undefined for shape <= 4, but got %1%.", dist.shape(), Policy());
}
return result;
} // kurtosis_excess
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_PARETO_HPP

View File

@@ -0,0 +1,527 @@
// 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 Simeon-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/special_functions/trunc.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 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 l_mean = 1) : m_l(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>(static_cast<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>(static_cast<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 = 0;
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);
}
return boost::math::gamma_p_derivative(k+1, mean, Policy());
} // 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 = 0;
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 = 0;
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.
static const char* function = "boost::math::quantile(const poisson_distribution<%1%>&, %1%)";
RealType result = 0; // of Argument checks:
if(false == poisson_detail::check_prob(
function,
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(
function,
dist.mean(),
&result, Policy()))
{
return result;
}
}
if(p == 0)
{
return 0; // Exact result regardless of discrete-quantile Policy
}
if(p == 1)
{
return policies::raise_overflow_error<RealType>(function, 0, Policy());
}
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, RealType(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,
false,
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:
static const char* function = "boost::math::quantile(complement(const poisson_distribution<%1%>&, %1%))";
RealType q = c.param;
const poisson_distribution<RealType, Policy>& dist = c.dist;
RealType result = 0; // of argument checks.
if(false == poisson_detail::check_prob(
function,
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(
function,
dist.mean(),
&result, Policy()))
{
return result;
}
}
if(q == 0)
{
return policies::raise_overflow_error<RealType>(function, 0, Policy());
}
if(q == 1)
{
return 0; // Exact result regardless of discrete-quantile Policy
}
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, RealType(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,
q,
true,
guess,
factor,
RealType(1),
discrete_type(),
max_iter);
} // quantile complement.
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#include <boost/math/distributions/detail/inv_discrete_quantile.hpp>
#endif // BOOST_MATH_SPECIAL_POISSON_HPP

View File

@@ -0,0 +1,301 @@
// 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 <boost/config/no_tr1/cmath.hpp>
#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) || (!(boost::math::isfinite)(sigma)))
{
*presult = policies::raise_domain_error<RealType>(
function,
"The scale parameter \"sigma\" must be > 0 and finite, 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) || (boost::math::isnan)(x))
{
*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 l_sigma = 1)
: m_sigma(l_sigma)
{
RealType err;
detail::verify_sigma("boost::math::rayleigh_distribution<%1%>::rayleigh_distribution", l_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>(0), std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : 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>(static_cast<RealType>(0), 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 = 0;
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;
}
if((boost::math::isinf)(x))
{
return 0;
}
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 = 0;
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 = 0;
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 = 0;
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;
}
RealType ea = x * x / (2 * sigma * sigma);
// Fix for VC11/12 x64 bug in exp(float):
if (ea >= tools::max_value<RealType>())
return 0;
result = exp(-ea);
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 = 0;
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 = 0;
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 = 0;
RealType sigma = dist.sigma();
static const char* function = "boost::math::variance(const rayleigh_distribution<%1%>&, %1%)";
if(false == detail::verify_sigma(function, sigma, &result, Policy()))
{
return result;
}
using boost::math::constants::four_minus_pi;
return four_minus_pi<RealType>() * sigma * sigma / 2;
} // variance
template <class RealType, class Policy>
inline RealType mode(const rayleigh_distribution<RealType, Policy>& dist)
{
return dist.sigma();
}
template <class RealType, class Policy>
inline RealType median(const rayleigh_distribution<RealType, Policy>& dist)
{
using boost::math::constants::root_ln_four;
return root_ln_four<RealType>() * dist.sigma();
}
template <class RealType, class Policy>
inline RealType skewness(const rayleigh_distribution<RealType, Policy>& /*dist*/)
{
// using namespace boost::math::constants;
return static_cast<RealType>(0.63111065781893713819189935154422777984404221106391L);
// Computed using NTL at 150 bit, about 50 decimal digits.
// return 2 * root_pi<RealType>() * pi_minus_three<RealType>() / pow23_four_minus_pi<RealType>();
}
template <class RealType, class Policy>
inline RealType kurtosis(const rayleigh_distribution<RealType, Policy>& /*dist*/)
{
// using namespace boost::math::constants;
return static_cast<RealType>(3.2450893006876380628486604106197544154170667057995L);
// Computed using NTL at 150 bit, about 50 decimal digits.
// return 3 - (6 * pi<RealType>() * pi<RealType>() - 24 * pi<RealType>() + 16) /
// (four_minus_pi<RealType>() * four_minus_pi<RealType>());
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const rayleigh_distribution<RealType, Policy>& /*dist*/)
{
//using namespace boost::math::constants;
// Computed using NTL at 150 bit, about 50 decimal digits.
return static_cast<RealType>(0.2450893006876380628486604106197544154170667057995L);
// return -(6 * pi<RealType>() * pi<RealType>() - 24 * pi<RealType>() + 16) /
// (four_minus_pi<RealType>() * four_minus_pi<RealType>());
} // kurtosis
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_rayleigh_HPP

View File

@@ -0,0 +1,719 @@
// Copyright Benjamin Sobotta 2012
// 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_SKEW_NORMAL_HPP
#define BOOST_STATS_SKEW_NORMAL_HPP
// http://en.wikipedia.org/wiki/Skew_normal_distribution
// http://azzalini.stat.unipd.it/SN/
// Also:
// Azzalini, A. (1985). "A class of distributions which includes the normal ones".
// Scand. J. Statist. 12: 171-178.
#include <boost/math/distributions/fwd.hpp> // TODO add skew_normal distribution to fwd.hpp!
#include <boost/math/special_functions/owens_t.hpp> // Owen's T function
#include <boost/math/distributions/complement.hpp>
#include <boost/math/distributions/normal.hpp>
#include <boost/math/distributions/detail/common_error_handling.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/tools/tuple.hpp>
#include <boost/math/tools/roots.hpp> // Newton-Raphson
#include <boost/assert.hpp>
#include <boost/math/distributions/detail/generic_mode.hpp> // pdf max finder.
#include <utility>
#include <algorithm> // std::lower_bound, std::distance
namespace boost{ namespace math{
namespace detail
{
template <class RealType, class Policy>
inline bool check_skew_normal_shape(
const char* function,
RealType shape,
RealType* result,
const Policy& pol)
{
if(!(boost::math::isfinite)(shape))
{
*result =
policies::raise_domain_error<RealType>(function,
"Shape parameter is %1%, but must be finite!",
shape, pol);
return false;
}
return true;
}
} // namespace detail
template <class RealType = double, class Policy = policies::policy<> >
class skew_normal_distribution
{
public:
typedef RealType value_type;
typedef Policy policy_type;
skew_normal_distribution(RealType l_location = 0, RealType l_scale = 1, RealType l_shape = 0)
: location_(l_location), scale_(l_scale), shape_(l_shape)
{ // Default is a 'standard' normal distribution N01. (shape=0 results in the normal distribution with no skew)
static const char* function = "boost::math::skew_normal_distribution<%1%>::skew_normal_distribution";
RealType result;
detail::check_scale(function, l_scale, &result, Policy());
detail::check_location(function, l_location, &result, Policy());
detail::check_skew_normal_shape(function, l_shape, &result, Policy());
}
RealType location()const
{
return location_;
}
RealType scale()const
{
return scale_;
}
RealType shape()const
{
return shape_;
}
private:
//
// Data members:
//
RealType location_; // distribution location.
RealType scale_; // distribution scale.
RealType shape_; // distribution shape.
}; // class skew_normal_distribution
typedef skew_normal_distribution<double> skew_normal;
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> range(const skew_normal_distribution<RealType, Policy>& /*dist*/)
{ // Range of permissible values for random variable x.
using boost::math::tools::max_value;
return std::pair<RealType, RealType>(
std::numeric_limits<RealType>::has_infinity ? -std::numeric_limits<RealType>::infinity() : -max_value<RealType>(),
std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : max_value<RealType>()); // - to + max value.
}
template <class RealType, class Policy>
inline const std::pair<RealType, RealType> support(const skew_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 skew_normal_distribution<RealType, Policy>& dist, const RealType& x)
{
const RealType scale = dist.scale();
const RealType location = dist.location();
const RealType shape = dist.shape();
static const char* function = "boost::math::pdf(const skew_normal_distribution<%1%>&, %1%)";
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if(false == detail::check_location(function, location, &result, Policy()))
{
return result;
}
if(false == detail::check_skew_normal_shape(function, shape, &result, Policy()))
{
return result;
}
if((boost::math::isinf)(x))
{
return 0; // pdf + and - infinity is zero.
}
// Below 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;
//}
if(false == detail::check_x(function, x, &result, Policy()))
{
return result;
}
const RealType transformed_x = (x-location)/scale;
normal_distribution<RealType, Policy> std_normal;
result = pdf(std_normal, transformed_x) * cdf(std_normal, shape*transformed_x) * 2 / scale;
return result;
} // pdf
template <class RealType, class Policy>
inline RealType cdf(const skew_normal_distribution<RealType, Policy>& dist, const RealType& x)
{
const RealType scale = dist.scale();
const RealType location = dist.location();
const RealType shape = dist.shape();
static const char* function = "boost::math::cdf(const skew_normal_distribution<%1%>&, %1%)";
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if(false == detail::check_location(function, location, &result, Policy()))
{
return result;
}
if(false == detail::check_skew_normal_shape(function, shape, &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;
}
const RealType transformed_x = (x-location)/scale;
normal_distribution<RealType, Policy> std_normal;
result = cdf(std_normal, transformed_x) - owens_t(transformed_x, shape)*static_cast<RealType>(2);
return result;
} // cdf
template <class RealType, class Policy>
inline RealType cdf(const complemented2_type<skew_normal_distribution<RealType, Policy>, RealType>& c)
{
const RealType scale = c.dist.scale();
const RealType location = c.dist.location();
const RealType shape = c.dist.shape();
const RealType x = c.param;
static const char* function = "boost::math::cdf(const complement(skew_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 = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
return result;
if(false == detail::check_location(function, location, &result, Policy()))
return result;
if(false == detail::check_skew_normal_shape(function, shape, &result, Policy()))
return result;
if(false == detail::check_x(function, x, &result, Policy()))
return result;
const RealType transformed_x = (x-location)/scale;
normal_distribution<RealType, Policy> std_normal;
result = cdf(complement(std_normal, transformed_x)) + owens_t(transformed_x, shape)*static_cast<RealType>(2);
return result;
} // cdf complement
template <class RealType, class Policy>
inline RealType location(const skew_normal_distribution<RealType, Policy>& dist)
{
return dist.location();
}
template <class RealType, class Policy>
inline RealType scale(const skew_normal_distribution<RealType, Policy>& dist)
{
return dist.scale();
}
template <class RealType, class Policy>
inline RealType shape(const skew_normal_distribution<RealType, Policy>& dist)
{
return dist.shape();
}
template <class RealType, class Policy>
inline RealType mean(const skew_normal_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
using namespace boost::math::constants;
//const RealType delta = dist.shape() / sqrt(static_cast<RealType>(1)+dist.shape()*dist.shape());
//return dist.location() + dist.scale() * delta * root_two_div_pi<RealType>();
return dist.location() + dist.scale() * dist.shape() / sqrt(pi<RealType>()+pi<RealType>()*dist.shape()*dist.shape()) * root_two<RealType>();
}
template <class RealType, class Policy>
inline RealType variance(const skew_normal_distribution<RealType, Policy>& dist)
{
using namespace boost::math::constants;
const RealType delta2 = static_cast<RealType>(1) / (static_cast<RealType>(1)+static_cast<RealType>(1)/(dist.shape()*dist.shape()));
//const RealType inv_delta2 = static_cast<RealType>(1)+static_cast<RealType>(1)/(dist.shape()*dist.shape());
RealType variance = dist.scale()*dist.scale()*(static_cast<RealType>(1)-two_div_pi<RealType>()*delta2);
//RealType variance = dist.scale()*dist.scale()*(static_cast<RealType>(1)-two_div_pi<RealType>()/inv_delta2);
return variance;
}
namespace detail
{
/*
TODO No closed expression for mode, so use max of pdf.
*/
template <class RealType, class Policy>
inline RealType mode_fallback(const skew_normal_distribution<RealType, Policy>& dist)
{ // mode.
static const char* function = "mode(skew_normal_distribution<%1%> const&)";
const RealType scale = dist.scale();
const RealType location = dist.location();
const RealType shape = dist.shape();
RealType result;
if(!detail::check_scale(
function,
scale, &result, Policy())
||
!detail::check_skew_normal_shape(
function,
shape,
&result,
Policy()))
return result;
if( shape == 0 )
{
return location;
}
if( shape < 0 )
{
skew_normal_distribution<RealType, Policy> D(0, 1, -shape);
result = mode_fallback(D);
result = location-scale*result;
return result;
}
BOOST_MATH_STD_USING
// 21 elements
static const RealType shapes[] = {
0.0,
1.000000000000000e-004,
2.069138081114790e-004,
4.281332398719396e-004,
8.858667904100824e-004,
1.832980710832436e-003,
3.792690190732250e-003,
7.847599703514606e-003,
1.623776739188722e-002,
3.359818286283781e-002,
6.951927961775606e-002,
1.438449888287663e-001,
2.976351441631319e-001,
6.158482110660261e-001,
1.274274985703135e+000,
2.636650898730361e+000,
5.455594781168514e+000,
1.128837891684688e+001,
2.335721469090121e+001,
4.832930238571753e+001,
1.000000000000000e+002};
// 21 elements
static const RealType guess[] = {
0.0,
5.000050000525391e-005,
1.500015000148736e-004,
3.500035000350010e-004,
7.500075000752560e-004,
1.450014500145258e-003,
3.050030500305390e-003,
6.250062500624765e-003,
1.295012950129504e-002,
2.675026750267495e-002,
5.525055250552491e-002,
1.132511325113255e-001,
2.249522495224952e-001,
3.992539925399257e-001,
5.353553535535358e-001,
4.954549545495457e-001,
3.524535245352451e-001,
2.182521825218249e-001,
1.256512565125654e-001,
6.945069450694508e-002,
3.735037350373460e-002
};
const RealType* result_ptr = std::lower_bound(shapes, shapes+21, shape);
typedef typename std::iterator_traits<RealType*>::difference_type diff_type;
const diff_type d = std::distance(shapes, result_ptr);
BOOST_ASSERT(d > static_cast<diff_type>(0));
// refine
if(d < static_cast<diff_type>(21)) // shape smaller 100
{
result = guess[d-static_cast<diff_type>(1)]
+ (guess[d]-guess[d-static_cast<diff_type>(1)])/(shapes[d]-shapes[d-static_cast<diff_type>(1)])
* (shape-shapes[d-static_cast<diff_type>(1)]);
}
else // shape greater 100
{
result = 1e-4;
}
skew_normal_distribution<RealType, Policy> helper(0, 1, shape);
result = detail::generic_find_mode_01(helper, result, function);
result = result*scale + location;
return result;
} // mode_fallback
/*
* TODO No closed expression for mode, so use f'(x) = 0
*/
template <class RealType, class Policy>
struct skew_normal_mode_functor
{
skew_normal_mode_functor(const boost::math::skew_normal_distribution<RealType, Policy> dist)
: distribution(dist)
{
}
boost::math::tuple<RealType, RealType> operator()(RealType const& x)
{
normal_distribution<RealType, Policy> std_normal;
const RealType shape = distribution.shape();
const RealType pdf_x = pdf(distribution, x);
const RealType normpdf_x = pdf(std_normal, x);
const RealType normpdf_ax = pdf(std_normal, x*shape);
RealType fx = static_cast<RealType>(2)*shape*normpdf_ax*normpdf_x - x*pdf_x;
RealType dx = static_cast<RealType>(2)*shape*x*normpdf_x*normpdf_ax*(static_cast<RealType>(1) + shape*shape) + pdf_x + x*fx;
// return both function evaluation difference f(x) and 1st derivative f'(x).
return boost::math::make_tuple(fx, -dx);
}
private:
const boost::math::skew_normal_distribution<RealType, Policy> distribution;
};
} // namespace detail
template <class RealType, class Policy>
inline RealType mode(const skew_normal_distribution<RealType, Policy>& dist)
{
const RealType scale = dist.scale();
const RealType location = dist.location();
const RealType shape = dist.shape();
static const char* function = "boost::math::mode(const skew_normal_distribution<%1%>&, %1%)";
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
return result;
if(false == detail::check_location(function, location, &result, Policy()))
return result;
if(false == detail::check_skew_normal_shape(function, shape, &result, Policy()))
return result;
if( shape == 0 )
{
return location;
}
if( shape < 0 )
{
skew_normal_distribution<RealType, Policy> D(0, 1, -shape);
result = mode(D);
result = location-scale*result;
return result;
}
// 21 elements
static const RealType shapes[] = {
0.0,
static_cast<RealType>(1.000000000000000e-004),
static_cast<RealType>(2.069138081114790e-004),
static_cast<RealType>(4.281332398719396e-004),
static_cast<RealType>(8.858667904100824e-004),
static_cast<RealType>(1.832980710832436e-003),
static_cast<RealType>(3.792690190732250e-003),
static_cast<RealType>(7.847599703514606e-003),
static_cast<RealType>(1.623776739188722e-002),
static_cast<RealType>(3.359818286283781e-002),
static_cast<RealType>(6.951927961775606e-002),
static_cast<RealType>(1.438449888287663e-001),
static_cast<RealType>(2.976351441631319e-001),
static_cast<RealType>(6.158482110660261e-001),
static_cast<RealType>(1.274274985703135e+000),
static_cast<RealType>(2.636650898730361e+000),
static_cast<RealType>(5.455594781168514e+000),
static_cast<RealType>(1.128837891684688e+001),
static_cast<RealType>(2.335721469090121e+001),
static_cast<RealType>(4.832930238571753e+001),
static_cast<RealType>(1.000000000000000e+002)
};
// 21 elements
static const RealType guess[] = {
0.0,
static_cast<RealType>(5.000050000525391e-005),
static_cast<RealType>(1.500015000148736e-004),
static_cast<RealType>(3.500035000350010e-004),
static_cast<RealType>(7.500075000752560e-004),
static_cast<RealType>(1.450014500145258e-003),
static_cast<RealType>(3.050030500305390e-003),
static_cast<RealType>(6.250062500624765e-003),
static_cast<RealType>(1.295012950129504e-002),
static_cast<RealType>(2.675026750267495e-002),
static_cast<RealType>(5.525055250552491e-002),
static_cast<RealType>(1.132511325113255e-001),
static_cast<RealType>(2.249522495224952e-001),
static_cast<RealType>(3.992539925399257e-001),
static_cast<RealType>(5.353553535535358e-001),
static_cast<RealType>(4.954549545495457e-001),
static_cast<RealType>(3.524535245352451e-001),
static_cast<RealType>(2.182521825218249e-001),
static_cast<RealType>(1.256512565125654e-001),
static_cast<RealType>(6.945069450694508e-002),
static_cast<RealType>(3.735037350373460e-002)
};
const RealType* result_ptr = std::lower_bound(shapes, shapes+21, shape);
typedef typename std::iterator_traits<RealType*>::difference_type diff_type;
const diff_type d = std::distance(shapes, result_ptr);
BOOST_ASSERT(d > static_cast<diff_type>(0));
// TODO: make the search bounds smarter, depending on the shape parameter
RealType search_min = 0; // below zero was caught above
RealType search_max = 0.55f; // will never go above 0.55
// refine
if(d < static_cast<diff_type>(21)) // shape smaller 100
{
// it is safe to assume that d > 0, because shape==0.0 is caught earlier
result = guess[d-static_cast<diff_type>(1)]
+ (guess[d]-guess[d-static_cast<diff_type>(1)])/(shapes[d]-shapes[d-static_cast<diff_type>(1)])
* (shape-shapes[d-static_cast<diff_type>(1)]);
}
else // shape greater 100
{
result = 1e-4f;
search_max = guess[19]; // set 19 instead of 20 to have a safety margin because the table may not be exact @ shape=100
}
const int get_digits = policies::digits<RealType, Policy>();// get digits from policy,
boost::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
skew_normal_distribution<RealType, Policy> helper(0, 1, shape);
result = tools::newton_raphson_iterate(detail::skew_normal_mode_functor<RealType, Policy>(helper), result,
search_min, search_max, get_digits, m);
result = result*scale + location;
return result;
}
template <class RealType, class Policy>
inline RealType skewness(const skew_normal_distribution<RealType, Policy>& dist)
{
BOOST_MATH_STD_USING // for ADL of std functions
using namespace boost::math::constants;
static const RealType factor = four_minus_pi<RealType>()/static_cast<RealType>(2);
const RealType delta = dist.shape() / sqrt(static_cast<RealType>(1)+dist.shape()*dist.shape());
return factor * pow(root_two_div_pi<RealType>() * delta, 3) /
pow(static_cast<RealType>(1)-two_div_pi<RealType>()*delta*delta, static_cast<RealType>(1.5));
}
template <class RealType, class Policy>
inline RealType kurtosis(const skew_normal_distribution<RealType, Policy>& dist)
{
return kurtosis_excess(dist)+static_cast<RealType>(3);
}
template <class RealType, class Policy>
inline RealType kurtosis_excess(const skew_normal_distribution<RealType, Policy>& dist)
{
using namespace boost::math::constants;
static const RealType factor = pi_minus_three<RealType>()*static_cast<RealType>(2);
const RealType delta2 = static_cast<RealType>(1) / (static_cast<RealType>(1)+static_cast<RealType>(1)/(dist.shape()*dist.shape()));
const RealType x = static_cast<RealType>(1)-two_div_pi<RealType>()*delta2;
const RealType y = two_div_pi<RealType>() * delta2;
return factor * y*y / (x*x);
}
namespace detail
{
template <class RealType, class Policy>
struct skew_normal_quantile_functor
{
skew_normal_quantile_functor(const boost::math::skew_normal_distribution<RealType, Policy> dist, RealType const& p)
: distribution(dist), prob(p)
{
}
boost::math::tuple<RealType, RealType> operator()(RealType const& x)
{
RealType c = cdf(distribution, x);
RealType fx = c - prob; // Difference cdf - value - to minimize.
RealType dx = pdf(distribution, x); // pdf is 1st derivative.
// return both function evaluation difference f(x) and 1st derivative f'(x).
return boost::math::make_tuple(fx, dx);
}
private:
const boost::math::skew_normal_distribution<RealType, Policy> distribution;
RealType prob;
};
} // namespace detail
template <class RealType, class Policy>
inline RealType quantile(const skew_normal_distribution<RealType, Policy>& dist, const RealType& p)
{
const RealType scale = dist.scale();
const RealType location = dist.location();
const RealType shape = dist.shape();
static const char* function = "boost::math::quantile(const skew_normal_distribution<%1%>&, %1%)";
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
return result;
if(false == detail::check_location(function, location, &result, Policy()))
return result;
if(false == detail::check_skew_normal_shape(function, shape, &result, Policy()))
return result;
if(false == detail::check_probability(function, p, &result, Policy()))
return result;
// Compute initial guess via Cornish-Fisher expansion.
RealType x = -boost::math::erfc_inv(2 * p, Policy()) * constants::root_two<RealType>();
// Avoid unnecessary computations if there is no skew.
if(shape != 0)
{
const RealType skew = skewness(dist);
const RealType exk = kurtosis_excess(dist);
x = x + (x*x-static_cast<RealType>(1))*skew/static_cast<RealType>(6)
+ x*(x*x-static_cast<RealType>(3))*exk/static_cast<RealType>(24)
- x*(static_cast<RealType>(2)*x*x-static_cast<RealType>(5))*skew*skew/static_cast<RealType>(36);
} // if(shape != 0)
result = standard_deviation(dist)*x+mean(dist);
// handle special case of non-skew normal distribution.
if(shape == 0)
return result;
// refine the result by numerically searching the root of (p-cdf)
const RealType search_min = range(dist).first;
const RealType search_max = range(dist).second;
const int get_digits = policies::digits<RealType, Policy>();// get digits from policy,
boost::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
result = tools::newton_raphson_iterate(detail::skew_normal_quantile_functor<RealType, Policy>(dist, p), result,
search_min, search_max, get_digits, m);
return result;
} // quantile
template <class RealType, class Policy>
inline RealType quantile(const complemented2_type<skew_normal_distribution<RealType, Policy>, RealType>& c)
{
const RealType scale = c.dist.scale();
const RealType location = c.dist.location();
const RealType shape = c.dist.shape();
static const char* function = "boost::math::quantile(const complement(skew_normal_distribution<%1%>&), %1%)";
RealType result = 0;
if(false == detail::check_scale(function, scale, &result, Policy()))
return result;
if(false == detail::check_location(function, location, &result, Policy()))
return result;
if(false == detail::check_skew_normal_shape(function, shape, &result, Policy()))
return result;
RealType q = c.param;
if(false == detail::check_probability(function, q, &result, Policy()))
return result;
skew_normal_distribution<RealType, Policy> D(-location, scale, -shape);
result = -quantile(D, q);
return result;
} // quantile
} // 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_SKEW_NORMAL_HPP

View File

@@ -0,0 +1,490 @@
// Copyright John Maddock 2006.
// Copyright Paul A. Bristow 2006, 2012.
// Copyright Thomas Mang 2012.
// 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 <boost/math/distributions/normal.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 df) : df_(df)
{ // Constructor.
RealType result;
detail::check_df_gt0_to_inf( // Checks that df > 0 or df == inf.
"boost::math::students_t_distribution<%1%>::students_t_distribution", df_, &result, Policy());
} // students_t_distribution
RealType degrees_of_freedom()const
{
return df_;
}
// Parameter estimation:
static RealType find_degrees_of_freedom(
RealType difference_from_mean,
RealType alpha,
RealType beta,
RealType sd,
RealType hint = 100);
private:
// Data member:
RealType df_; // degrees of freedom is a real number or +infinity.
};
typedef students_t_distribution<double> students_t; // Convenience typedef for double version.
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.
// NOT including infinity.
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& x)
{
BOOST_FPU_EXCEPTION_GUARD
BOOST_MATH_STD_USING // for ADL of std functions.
RealType error_result;
if(false == detail::check_x(
"boost::math::pdf(const students_t_distribution<%1%>&, %1%)", x, &error_result, Policy()))
return error_result;
RealType df = dist.degrees_of_freedom();
if(false == detail::check_df_gt0_to_inf( // Check that df > 0 or == +infinity.
"boost::math::pdf(const students_t_distribution<%1%>&, %1%)", df, &error_result, Policy()))
return error_result;
RealType result;
if ((boost::math::isinf)(x))
{ // +infinity.
normal_distribution<RealType, Policy> n(0, 1);
result = pdf(n, x);
return result;
}
RealType limit = policies::get_epsilon<RealType, Policy>();
// Use policies so that if policy requests lower precision,
// then get the normal distribution approximation earlier.
limit = static_cast<RealType>(1) / limit; // 1/eps
// for 64-bit double 1/eps = 4503599627370496
if (df > limit)
{ // Special case for really big degrees_of_freedom > 1 / eps
// - use normal distribution which is much faster and more accurate.
normal_distribution<RealType, Policy> n(0, 1);
result = pdf(n, x);
}
else
{ //
RealType basem1 = x * x / df;
if(basem1 < 0.125)
{
result = exp(-boost::math::log1p(basem1, Policy()) * (1+df) / 2);
}
else
{
result = pow(1 / (1 + basem1), (df + 1) / 2);
}
result /= sqrt(df) * boost::math::beta(df / 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& x)
{
RealType error_result;
if(false == detail::check_x(
"boost::math::pdf(const students_t_distribution<%1%>&, %1%)", x, &error_result, Policy()))
return error_result;
RealType df = dist.degrees_of_freedom();
// Error check:
if(false == detail::check_df_gt0_to_inf( // Check that df > 0 or == +infinity.
"boost::math::cdf(const students_t_distribution<%1%>&, %1%)", df, &error_result, Policy()))
return error_result;
if (x == 0)
{ // Special case with exact result.
return static_cast<RealType>(0.5);
}
if ((boost::math::isinf)(x))
{ // +infinity.
normal_distribution<RealType, Policy> n(0, 1);
RealType result = cdf(n, x);
return result;
}
RealType limit = policies::get_epsilon<RealType, Policy>();
// Use policies so that if policy requests lower precision,
// then get the normal distribution approximation earlier.
limit = static_cast<RealType>(1) / limit; // 1/eps
// for 64-bit double 1/eps = 4503599627370496
if (df > limit)
{ // Special case for really big degrees_of_freedom > 1 / eps (perhaps infinite?)
// - use normal distribution which is much faster and more accurate.
normal_distribution<RealType, Policy> n(0, 1);
RealType result = cdf(n, x);
return result;
}
else
{ // normal df case.
//
// 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 x2 = x * x;
RealType probability;
if(df > 2 * x2)
{
RealType z = x2 / (df + x2);
probability = ibetac(static_cast<RealType>(0.5), df / 2, z, Policy()) / 2;
}
else
{
RealType z = df / (df + x2);
probability = ibeta(df / 2, static_cast<RealType>(0.5), z, Policy()) / 2;
}
return (x > 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 probability = p;
// Check for domain errors:
RealType df = dist.degrees_of_freedom();
static const char* function = "boost::math::quantile(const students_t_distribution<%1%>&, %1%)";
RealType error_result;
if(false == (detail::check_df_gt0_to_inf( // Check that df > 0 or == +infinity.
function, df, &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; //
//
#if 0
// This next block is disabled in favour of a faster method than
// incomplete beta inverse, but code retained for future reference:
//
// 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(df, 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>())
{
return 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 mode(const students_t_distribution<RealType, Policy>& /*dist*/)
{
// Assume no checks on degrees of freedom are useful (unlike mean).
return 0; // Always zero by definition.
}
template <class RealType, class Policy>
inline RealType median(const students_t_distribution<RealType, Policy>& /*dist*/)
{
// Assume no checks on degrees of freedom are useful (unlike mean).
return 0; // Always zero by definition.
}
// See section 5.1 on moments at http://en.wikipedia.org/wiki/Student%27s_t-distribution
template <class RealType, class Policy>
inline RealType mean(const students_t_distribution<RealType, Policy>& dist)
{ // Revised for https://svn.boost.org/trac/boost/ticket/7177
RealType df = dist.degrees_of_freedom();
if(((boost::math::isnan)(df)) || (df <= 1) )
{ // mean is undefined for moment <= 1!
return policies::raise_domain_error<RealType>(
"boost::math::mean(students_t_distribution<%1%> const&, %1%)",
"Mean is undefined for degrees of freedom < 1 but got %1%.", df, Policy());
return std::numeric_limits<RealType>::quiet_NaN();
}
return 0;
} // mean
template <class RealType, class Policy>
inline RealType variance(const students_t_distribution<RealType, Policy>& dist)
{ // http://en.wikipedia.org/wiki/Student%27s_t-distribution
// Revised for https://svn.boost.org/trac/boost/ticket/7177
RealType df = dist.degrees_of_freedom();
if ((boost::math::isnan)(df) || (df <= 2))
{ // NaN or undefined for <= 2.
return policies::raise_domain_error<RealType>(
"boost::math::variance(students_t_distribution<%1%> const&, %1%)",
"variance is undefined for degrees of freedom <= 2, but got %1%.",
df, Policy());
return std::numeric_limits<RealType>::quiet_NaN(); // Undefined.
}
if ((boost::math::isinf)(df))
{ // +infinity.
return 1;
}
RealType limit = policies::get_epsilon<RealType, Policy>();
// Use policies so that if policy requests lower precision,
// then get the normal distribution approximation earlier.
limit = static_cast<RealType>(1) / limit; // 1/eps
// for 64-bit double 1/eps = 4503599627370496
if (df > limit)
{ // Special case for really big degrees_of_freedom > 1 / eps.
return 1;
}
else
{
return df / (df - 2);
}
} // variance
template <class RealType, class Policy>
inline RealType skewness(const students_t_distribution<RealType, Policy>& dist)
{
RealType df = dist.degrees_of_freedom();
if( ((boost::math::isnan)(df)) || (dist.degrees_of_freedom() <= 3))
{ // Undefined for moment k = 3.
return 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 std::numeric_limits<RealType>::quiet_NaN();
}
return 0; // For all valid df, including infinity.
} // skewness
template <class RealType, class Policy>
inline RealType kurtosis(const students_t_distribution<RealType, Policy>& dist)
{
RealType df = dist.degrees_of_freedom();
if(((boost::math::isnan)(df)) || (df <= 4))
{ // Undefined or infinity for moment k = 4.
return policies::raise_domain_error<RealType>(
"boost::math::kurtosis(students_t_distribution<%1%> const&, %1%)",
"Kurtosis is undefined for degrees of freedom <= 4, but got %1%.",
df, Policy());
return std::numeric_limits<RealType>::quiet_NaN(); // Undefined.
}
if ((boost::math::isinf)(df))
{ // +infinity.
return 3;
}
RealType limit = policies::get_epsilon<RealType, Policy>();
// Use policies so that if policy requests lower precision,
// then get the normal distribution approximation earlier.
limit = static_cast<RealType>(1) / limit; // 1/eps
// for 64-bit double 1/eps = 4503599627370496
if (df > limit)
{ // Special case for really big degrees_of_freedom > 1 / eps.
return 3;
}
else
{
//return 3 * (df - 2) / (df - 4); re-arranged to
return 6 / (df - 4) + 3;
}
} // kurtosis
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(((boost::math::isnan)(df)) || (df <= 4))
{ // Undefined or infinity for moment k = 4.
return policies::raise_domain_error<RealType>(
"boost::math::kurtosis_excess(students_t_distribution<%1%> const&, %1%)",
"Kurtosis_excess is undefined for degrees of freedom <= 4, but got %1%.",
df, Policy());
return std::numeric_limits<RealType>::quiet_NaN(); // Undefined.
}
if ((boost::math::isinf)(df))
{ // +infinity.
return 0;
}
RealType limit = policies::get_epsilon<RealType, Policy>();
// Use policies so that if policy requests lower precision,
// then get the normal distribution approximation earlier.
limit = static_cast<RealType>(1) / limit; // 1/eps
// for 64-bit double 1/eps = 4503599627370496
if (df > limit)
{ // Special case for really big degrees_of_freedom > 1 / eps.
return 0;
}
else
{
return 6 / (df - 4);
}
}
} // namespace math
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_STUDENTS_T_HPP

View File

@@ -0,0 +1,531 @@
// 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
// Note that the 'constructors' defined by Wolfram are difference from those here,
// for example
// N[variance[triangulardistribution{1, +2}, 1.5], 50] computes
// 0.041666666666666666666666666666666666666666666666667
// TriangularDistribution{1, +2}, 1.5 is the analog of triangular_distribution(1, 1.5, 2)
// 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) == false)
|| (check_triangular_mode(function, mode, result, pol) == false)
|| (check_triangular_upper(function, upper, result, pol) == false))
{ // Some parameter not finite.
return false;
}
else if (lower >= upper) // lower == upper NOT useful.
{ // lower >= upper.
*result = policies::raise_domain_error<RealType>(
function,
"lower parameter is %1%, but must be less than upper!", lower, pol);
return false;
}
else
{ // Check lower <= mode <= upper.
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; // All OK.
}
} // 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 l_lower = -1, RealType l_mode = 0, RealType l_upper = 1)
: m_lower(l_lower), m_mode(l_mode), m_upper(l_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",l_lower, l_mode, l_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 = 0; // 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) : RealType(0);
}
else if (x == upper)
{
return (mode == upper) ? 2 / (upper - lower) : RealType(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 = 0; // 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 = 0; // 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 = 0; // 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 = 0; // 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 = 0; // 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 = 0; // 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 = 0; // 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 = 0; // 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 = 0; // of checks.
if(false == boost::math::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)));
// #11768: Skewness formula for triangular distribution is incorrect - corrected 29 Oct 2015 for release 1.61.
} // 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 = 0; // 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 = 0; // of checks.
if(false == detail::check_triangular(function,lower, mode, upper, &result, Policy()))
{
return result;
}
return static_cast<RealType>(-3)/5; // - 3/5 = -0.6
// Assuming mathworld really means kurtosis excess? Wikipedia now corrected to match this.
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_TRIANGULAR_HPP

View File

@@ -0,0 +1,382 @@
// 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) == false)
|| (check_uniform_upper(function, upper, result, pol) == false))
{
return false;
}
else if (lower >= upper) // If lower == upper then 1 / (upper-lower) = 1/0 = +infinity!
{ // 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;
}
else
{ // All OK,
return true;
}
} // 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 l_lower = 0, RealType l_upper = 1) // Constructor.
: m_lower(l_lower), m_upper(l_upper) // Default is standard uniform distribution.
{
RealType result;
detail::check_uniform("boost::math::uniform_distribution<%1%>::uniform_distribution", l_lower, l_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'.
// Note RealType infinity is NOT permitted, only max_value.
}
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 = 0; // 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 = 0; // 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 = 0; // 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 = 0; // 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 1;
}
if (x > upper)
{
return 0;
}
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 = 0; // 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()))
{
return result;
}
if(q == 0)
{
return upper;
}
if(q == 1)
{
return lower;
}
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 = 0; // 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 = 0; // 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 = 0; // 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 = 0; // 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 = 0; // 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 = 0; // of checks.
if(false == detail::check_uniform("boost::math::kurtosis_execess(const uniform_distribution<%1%>&)", lower, upper, &result, Policy()))
{
return result;
}
return static_cast<RealType>(-6)/5; // -6/5 = -1.2;
} // RealType kurtosis_excess(const uniform_distribution<RealType, Policy>& dist)
template <class RealType, class Policy>
inline RealType kurtosis(const uniform_distribution<RealType, Policy>& dist)
{
return kurtosis_excess(dist) + 3;
}
} // namespace math
} // namespace boost
// This include must be at the end, *after* the accessors
// for this distribution have been defined, in order to
// keep compilers that support two-phase lookup happy.
#include <boost/math/distributions/detail/derived_accessors.hpp>
#endif // BOOST_STATS_UNIFORM_HPP

View File

@@ -0,0 +1,395 @@
// 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 l_shape, RealType l_scale = 1)
: m_shape(l_shape), m_scale(l_scale)
{
RealType result;
detail::check_weibull("boost::math::weibull_distribution<%1%>::weibull_distribution", l_scale, l_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>(static_cast<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;
using boost::math::tools::min_value;
return std::pair<RealType, RealType>(min_value<RealType>(), max_value<RealType>());
// A discontinuity at x == 0, so only support down to min_value.
}
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 = 0;
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)
{
if(shape == 1)
{
return 1 / scale;
}
if(shape > 1)
{
return 0;
}
return policies::raise_overflow_error<RealType>(function, 0, Policy());
}
result = exp(-pow(x / scale, shape));
result *= pow(x / scale, shape - 1) * shape / scale;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
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 = 0;
if(false == detail::check_weibull(function, scale, shape, &result, Policy()))
{
return result;
}
if(shape <= 1)
return 0;
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 = 0;
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 = 0;
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 = 0;
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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,847 @@
// 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 <cstring>
#include <typeinfo>
#include <cerrno>
#include <boost/config/no_tr1/complex.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <stdexcept>
#include <boost/math/tools/config.hpp>
#include <boost/math/policies/policy.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/throw_exception.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.
# pragma warning(disable: 4127) // conditional expression is constant
// 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 <sstream>
namespace boost{ namespace math{
class evaluation_error : public std::runtime_error
{
public:
evaluation_error(const std::string& s) : std::runtime_error(s){}
};
class rounding_error : public std::runtime_error
{
public:
rounding_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);
template <class T, class TargetType>
T user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t);
template <class T>
T user_indeterminate_result_error(const char* function, const char* message, const T& val);
namespace detail
{
template <class T>
std::string prec_format(const T& val)
{
typedef typename boost::math::policies::precision<T, boost::math::policies::policy<> >::type prec_type;
std::stringstream ss;
if(prec_type::value)
{
int prec = 2 + (prec_type::value * 30103UL) / 100000UL;
ss << std::setprecision(prec);
}
ss << val;
return ss.str();
}
inline void replace_all_in_string(std::string& result, const char* what, const char* with)
{
std::string::size_type pos = 0;
std::string::size_type slen = std::strlen(what);
std::string::size_type rlen = std::strlen(with);
while((pos = result.find(what, pos)) != std::string::npos)
{
result.replace(pos, slen, with);
pos += rlen;
}
}
template <class T>
inline const char* name_of()
{
#ifndef BOOST_NO_RTTI
return typeid(T).name();
#else
return "unknown";
#endif
}
template <> inline const char* name_of<float>(){ return "float"; }
template <> inline const char* name_of<double>(){ return "double"; }
template <> inline const char* name_of<long double>(){ return "long double"; }
#ifdef BOOST_MATH_USE_FLOAT128
template <>
inline const char* name_of<BOOST_MATH_FLOAT128_TYPE>()
{
return "__float128";
}
#endif
template <class E, class T>
void raise_error(const char* pfunction, const char* message)
{
if(pfunction == 0)
pfunction = "Unknown function operating on type %1%";
if(message == 0)
message = "Cause unknown";
std::string function(pfunction);
std::string msg("Error in function ");
#ifndef BOOST_NO_RTTI
replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of<T>());
#else
replace_all_in_string(function, "%1%", "Unknown");
#endif
msg += function;
msg += ": ";
msg += message;
E e(msg);
boost::throw_exception(e);
}
template <class E, class T>
void raise_error(const char* pfunction, const char* pmessage, const T& val)
{
if(pfunction == 0)
pfunction = "Unknown function operating on type %1%";
if(pmessage == 0)
pmessage = "Cause unknown: error caused by bad argument with value %1%";
std::string function(pfunction);
std::string message(pmessage);
std::string msg("Error in function ");
#ifndef BOOST_NO_RTTI
replace_all_in_string(function, "%1%", boost::math::policies::detail::name_of<T>());
#else
replace_all_in_string(function, "%1%", "Unknown");
#endif
msg += function;
msg += ": ";
std::string sval = prec_format(val);
replace_all_in_string(message, "%1%", sval.c_str());
msg += message;
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 BOOST_MATH_CONSTEXPR T raise_domain_error(
const char* ,
const char* ,
const T& ,
const ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
{
// 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>&) BOOST_MATH_NOEXCEPT(T)
{
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 BOOST_MATH_CONSTEXPR T raise_pole_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::pole_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
{
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 BOOST_MATH_CONSTEXPR 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>&) BOOST_MATH_NOEXCEPT(T)
{
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 should 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* function,
const char* message,
const T& val,
const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow", val);
// We should 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 BOOST_MATH_CONSTEXPR T raise_overflow_error(
const char* ,
const char* ,
const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
{
// 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 BOOST_MATH_CONSTEXPR T raise_overflow_error(
const char* ,
const char* ,
const T&,
const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
{
// 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>&) BOOST_MATH_NOEXCEPT(T)
{
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* ,
const char* ,
const T&,
const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
{
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_overflow_error(
const char* function,
const char* message,
const T& val,
const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
{
std::string m(message ? message : "");
std::string sval = prec_format(val);
replace_all_in_string(m, "%1%", sval.c_str());
return user_overflow_error(function, m.c_str(), 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 should never get here:
return 0;
}
template <class T>
inline BOOST_MATH_CONSTEXPR T raise_underflow_error(
const char* ,
const char* ,
const ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
{
// 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>&) BOOST_MATH_NOEXCEPT(T)
{
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 BOOST_MATH_CONSTEXPR T raise_denorm_error(
const char* ,
const char* ,
const T& val,
const ::boost::math::policies::denorm_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
{
// 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>&) BOOST_MATH_NOEXCEPT(T)
{
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 BOOST_MATH_CONSTEXPR T raise_evaluation_error(
const char* ,
const char* ,
const T& val,
const ::boost::math::policies::evaluation_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
{
// 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>&) BOOST_MATH_NOEXCEPT(T)
{
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);
}
template <class T, class TargetType>
inline TargetType raise_rounding_error(
const char* function,
const char* message,
const T& val,
const TargetType&,
const ::boost::math::policies::rounding_error< ::boost::math::policies::throw_on_error>&)
{
raise_error<boost::math::rounding_error, T>(function, message, val);
// we never get here:
return TargetType(0);
}
template <class T, class TargetType>
inline BOOST_MATH_CONSTEXPR TargetType raise_rounding_error(
const char* ,
const char* ,
const T& val,
const TargetType&,
const ::boost::math::policies::rounding_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
{
// This may or may not do the right thing, but the user asked for the error
// to be ignored so here we go anyway:
BOOST_STATIC_ASSERT(std::numeric_limits<TargetType>::is_specialized);
return val > 0 ? (std::numeric_limits<TargetType>::max)() : (std::numeric_limits<TargetType>::is_integer ? (std::numeric_limits<TargetType>::min)() : -(std::numeric_limits<TargetType>::max)());
}
template <class T, class TargetType>
inline TargetType raise_rounding_error(
const char* ,
const char* ,
const T& val,
const TargetType&,
const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
{
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:
BOOST_STATIC_ASSERT(std::numeric_limits<TargetType>::is_specialized);
return val > 0 ? (std::numeric_limits<TargetType>::max)() : (std::numeric_limits<TargetType>::is_integer ? (std::numeric_limits<TargetType>::min)() : -(std::numeric_limits<TargetType>::max)());
}
template <class T>
inline T raise_rounding_error(
const char* ,
const char* ,
const T& val,
const T&,
const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&) BOOST_MATH_NOEXCEPT(T)
{
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 > 0 ? boost::math::tools::max_value<T>() : -boost::math::tools::max_value<T>();
}
template <class T, class TargetType>
inline TargetType raise_rounding_error(
const char* function,
const char* message,
const T& val,
const TargetType& t,
const ::boost::math::policies::rounding_error< ::boost::math::policies::user_error>&)
{
return user_rounding_error(function, message, val, t);
}
template <class T, class R>
inline T raise_indeterminate_result_error(
const char* function,
const char* message,
const T& val,
const R& ,
const ::boost::math::policies::indeterminate_result_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, class R>
inline BOOST_MATH_CONSTEXPR T raise_indeterminate_result_error(
const char* ,
const char* ,
const T& ,
const R& result,
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::ignore_error>&) BOOST_MATH_NOEXCEPT(T)
{
// 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 result;
}
template <class T, class R>
inline T raise_indeterminate_result_error(
const char* ,
const char* ,
const T& ,
const R& result,
const ::boost::math::policies::indeterminate_result_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 result;
}
template <class T, class R>
inline T raise_indeterminate_result_error(
const char* function,
const char* message,
const T& val,
const R& ,
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::user_error>&)
{
return user_indeterminate_result_error(function, message, val);
}
} // namespace detail
template <class T, class Policy>
inline BOOST_MATH_CONSTEXPR T raise_domain_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
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 BOOST_MATH_CONSTEXPR T raise_pole_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
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 BOOST_MATH_CONSTEXPR T raise_overflow_error(const char* function, const char* message, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
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 BOOST_MATH_CONSTEXPR T raise_overflow_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
typedef typename Policy::overflow_error_type policy_type;
return detail::raise_overflow_error(
function, message ? message : "Overflow evaluating function at %1%",
val, policy_type());
}
template <class T, class Policy>
inline BOOST_MATH_CONSTEXPR T raise_underflow_error(const char* function, const char* message, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
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 BOOST_MATH_CONSTEXPR T raise_denorm_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
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 BOOST_MATH_CONSTEXPR T raise_evaluation_error(const char* function, const char* message, const T& val, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
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());
}
template <class T, class TargetType, class Policy>
inline BOOST_MATH_CONSTEXPR TargetType raise_rounding_error(const char* function, const char* message, const T& val, const TargetType& t, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
typedef typename Policy::rounding_error_type policy_type;
return detail::raise_rounding_error(
function, message ? message : "Value %1% can not be represented in the target integer type.",
val, t, policy_type());
}
template <class T, class R, class Policy>
inline BOOST_MATH_CONSTEXPR T raise_indeterminate_result_error(const char* function, const char* message, const T& val, const R& result, const Policy&) BOOST_NOEXCEPT_IF(is_noexcept_error_policy<Policy>::value && BOOST_MATH_IS_FLOAT(T))
{
typedef typename Policy::indeterminate_result_error_type policy_type;
return detail::raise_indeterminate_result_error(
function, message ? message : "Indeterminate result with value %1%",
val, result, 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_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
{
BOOST_MATH_STD_USING
if(fabs(val) > tools::max_value<R>())
{
boost::math::policies::detail::raise_overflow_error<R>(function, 0, pol);
*result = static_cast<R>(val);
return true;
}
return false;
}
template <class R, class T, class Policy>
inline bool check_overflow(std::complex<T> val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
{
typedef typename R::value_type r_type;
r_type re, im;
bool r = check_overflow<r_type>(val.real(), &re, function, pol);
r = check_overflow<r_type>(val.imag(), &im, function, pol) || r;
*result = R(re, im);
return r;
}
template <class R, class T, class Policy>
inline bool check_underflow(T val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
{
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_underflow(std::complex<T> val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
{
typedef typename R::value_type r_type;
r_type re, im;
bool r = check_underflow<r_type>(val.real(), &re, function, pol);
r = check_underflow<r_type>(val.imag(), &im, function, pol) || r;
*result = R(re, im);
return r;
}
template <class R, class T, class Policy>
inline bool check_denorm(T val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
{
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;
}
template <class R, class T, class Policy>
inline bool check_denorm(std::complex<T> val, R* result, const char* function, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && (Policy::value != throw_on_error) && (Policy::value != user_error))
{
typedef typename R::value_type r_type;
r_type re, im;
bool r = check_denorm<r_type>(val.real(), &re, function, pol);
r = check_denorm<r_type>(val.imag(), &im, function, pol) || r;
*result = R(re, im);
return r;
}
// Default instantiations with ignore_error policy.
template <class R, class T>
inline BOOST_MATH_CONSTEXPR bool check_overflow(T /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
{ return false; }
template <class R, class T>
inline BOOST_MATH_CONSTEXPR bool check_overflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
{ return false; }
template <class R, class T>
inline BOOST_MATH_CONSTEXPR bool check_underflow(T /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
{ return false; }
template <class R, class T>
inline BOOST_MATH_CONSTEXPR bool check_underflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
{ return false; }
template <class R, class T>
inline BOOST_MATH_CONSTEXPR bool check_denorm(T /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
{ return false; }
template <class R, class T>
inline BOOST_MATH_CONSTEXPR bool check_denorm(std::complex<T> /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T))
{ return false; }
} // namespace detail
template <class R, class Policy, class T>
inline R checked_narrowing_cast(T val, const char* function) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(R) && BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
{
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 = 0;
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 T, class Policy>
inline void check_series_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
{
if(max_iter >= policies::get_max_series_iterations<Policy>())
raise_evaluation_error<T>(
function,
"Series evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
}
template <class T, class Policy>
inline void check_root_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol) BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(T) && is_noexcept_error_policy<Policy>::value)
{
if(max_iter >= policies::get_max_root_iterations<Policy>())
raise_evaluation_error<T>(
function,
"Root finding evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
}
} //namespace policies
namespace detail{
//
// Simple helper function to assist in returning a pair from a single value,
// that value usually comes from one of the error handlers above:
//
template <class T>
std::pair<T, T> pair_from_single(const T& val) BOOST_MATH_NOEXCEPT(T)
{
return std::make_pair(val, val);
}
}
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
}} // namespaces boost/math
#endif // BOOST_MATH_POLICY_ERROR_HANDLING_HPP

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
// Copyright John Maddock 2006, 2007, 2012, 2014.
// Copyright Paul A. Bristow 2006, 2007, 2012
// 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/airy.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/bernoulli.hpp>
#include <boost/math/special_functions/bessel.hpp>
#include <boost/math/special_functions/bessel_prime.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_d.hpp>
#include <boost/math/special_functions/jacobi_zeta.hpp>
#include <boost/math/special_functions/heuman_lambda.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/ellint_rg.hpp>
#include <boost/math/special_functions/erf.hpp>
#include <boost/math/special_functions/expint.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/jacobi_elliptic.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/next.hpp>
#include <boost/math/special_functions/owens_t.hpp>
#include <boost/math/special_functions/polygamma.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>
#include <boost/math/special_functions/zeta.hpp>
#include <boost/math/special_functions/modf.hpp>
#include <boost/math/special_functions/round.hpp>
#include <boost/math/special_functions/trunc.hpp>
#include <boost/math/special_functions/pow.hpp>
#include <boost/math/special_functions/next.hpp>
#include <boost/math/special_functions/owens_t.hpp>
#include <boost/math/special_functions/hankel.hpp>
#include <boost/math/special_functions/ulp.hpp>
#include <boost/math/special_functions/relative_difference.hpp>
#endif // BOOST_MATH_SPECIAL_FUNCTIONS_HPP

View File

@@ -0,0 +1,104 @@
// boost asinh.hpp header file
// (C) Copyright Eric Ford 2001 & Hubert Holin.
// (C) Copyright John Maddock 2008.
// 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)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_ACOSH_HPP
#define BOOST_ACOSH_HPP
#ifdef _MSC_VER
#pragma once
#endif
#include <boost/config/no_tr1/cmath.hpp>
#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>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/constants/constants.hpp>
// This is the inverse of the hyperbolic cosine function.
namespace boost
{
namespace math
{
namespace detail
{
template<typename T, typename Policy>
inline T acosh_imp(const T x, const Policy& pol)
{
BOOST_MATH_STD_USING
if((x < 1) || (boost::math::isnan)(x))
{
return policies::raise_domain_error<T>(
"boost::math::acosh<%1%>(%1%)",
"acosh requires x >= 1, but got x = %1%.", x, pol);
}
else if ((x - 1) >= tools::root_epsilon<T>())
{
if (x > 1 / tools::root_epsilon<T>())
{
// http://functions.wolfram.com/ElementaryFunctions/ArcCosh/06/01/06/01/0001/
// approximation by laurent series in 1/x at 0+ order from -1 to 0
return log(x) + constants::ln_two<T>();
}
else if(x < 1.5f)
{
// This is just a rearrangement of the standard form below
// devised to minimse loss of precision when x ~ 1:
T y = x - 1;
return boost::math::log1p(y + sqrt(y * y + 2 * y), pol);
}
else
{
// http://functions.wolfram.com/ElementaryFunctions/ArcCosh/02/
return( log( x + sqrt(x * x - 1) ) );
}
}
else
{
// see http://functions.wolfram.com/ElementaryFunctions/ArcCosh/06/01/04/01/0001/
T y = x - 1;
// approximation by taylor series in y at 0 up to order 2
T result = sqrt(2 * y) * (1 - y /12 + 3 * y * y / 160);
return result;
}
}
}
template<typename T, typename Policy>
inline typename tools::promote_args<T>::type acosh(T x, const Policy&)
{
typedef typename tools::promote_args<T>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
detail::acosh_imp(static_cast<value_type>(x), forwarding_policy()),
"boost::math::acosh<%1%>(%1%)");
}
template<typename T>
inline typename tools::promote_args<T>::type acosh(T x)
{
return boost::math::acosh(x, policies::policy<>());
}
}
}
#endif /* BOOST_ACOSH_HPP */

View File

@@ -0,0 +1,469 @@
// Copyright John Maddock 2012.
// 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_AIRY_HPP
#define BOOST_MATH_AIRY_HPP
#include <limits>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/bessel.hpp>
#include <boost/math/special_functions/cbrt.hpp>
#include <boost/math/special_functions/detail/airy_ai_bi_zero.hpp>
#include <boost/math/tools/roots.hpp>
namespace boost{ namespace math{
namespace detail{
template <class T, class Policy>
T airy_ai_imp(T x, const Policy& pol)
{
BOOST_MATH_STD_USING
if(x < 0)
{
T p = (-x * sqrt(-x) * 2) / 3;
T v = T(1) / 3;
T j1 = boost::math::cyl_bessel_j(v, p, pol);
T j2 = boost::math::cyl_bessel_j(-v, p, pol);
T ai = sqrt(-x) * (j1 + j2) / 3;
//T bi = sqrt(-x / 3) * (j2 - j1);
return ai;
}
else if(fabs(x * x * x) / 6 < tools::epsilon<T>())
{
T tg = boost::math::tgamma(constants::twothirds<T>(), pol);
T ai = 1 / (pow(T(3), constants::twothirds<T>()) * tg);
//T bi = 1 / (sqrt(boost::math::cbrt(T(3))) * tg);
return ai;
}
else
{
T p = 2 * x * sqrt(x) / 3;
T v = T(1) / 3;
//T j1 = boost::math::cyl_bessel_i(-v, p, pol);
//T j2 = boost::math::cyl_bessel_i(v, p, pol);
//
// Note that although we can calculate ai from j1 and j2, the accuracy is horrible
// as we're subtracting two very large values, so use the Bessel K relation instead:
//
T ai = cyl_bessel_k(v, p, pol) * sqrt(x / 3) / boost::math::constants::pi<T>(); //sqrt(x) * (j1 - j2) / 3;
//T bi = sqrt(x / 3) * (j1 + j2);
return ai;
}
}
template <class T, class Policy>
T airy_bi_imp(T x, const Policy& pol)
{
BOOST_MATH_STD_USING
if(x < 0)
{
T p = (-x * sqrt(-x) * 2) / 3;
T v = T(1) / 3;
T j1 = boost::math::cyl_bessel_j(v, p, pol);
T j2 = boost::math::cyl_bessel_j(-v, p, pol);
//T ai = sqrt(-x) * (j1 + j2) / 3;
T bi = sqrt(-x / 3) * (j2 - j1);
return bi;
}
else if(fabs(x * x * x) / 6 < tools::epsilon<T>())
{
T tg = boost::math::tgamma(constants::twothirds<T>(), pol);
//T ai = 1 / (pow(T(3), constants::twothirds<T>()) * tg);
T bi = 1 / (sqrt(boost::math::cbrt(T(3))) * tg);
return bi;
}
else
{
T p = 2 * x * sqrt(x) / 3;
T v = T(1) / 3;
T j1 = boost::math::cyl_bessel_i(-v, p, pol);
T j2 = boost::math::cyl_bessel_i(v, p, pol);
T bi = sqrt(x / 3) * (j1 + j2);
return bi;
}
}
template <class T, class Policy>
T airy_ai_prime_imp(T x, const Policy& pol)
{
BOOST_MATH_STD_USING
if(x < 0)
{
T p = (-x * sqrt(-x) * 2) / 3;
T v = T(2) / 3;
T j1 = boost::math::cyl_bessel_j(v, p, pol);
T j2 = boost::math::cyl_bessel_j(-v, p, pol);
T aip = -x * (j1 - j2) / 3;
return aip;
}
else if(fabs(x * x) / 2 < tools::epsilon<T>())
{
T tg = boost::math::tgamma(constants::third<T>(), pol);
T aip = 1 / (boost::math::cbrt(T(3)) * tg);
return -aip;
}
else
{
T p = 2 * x * sqrt(x) / 3;
T v = T(2) / 3;
//T j1 = boost::math::cyl_bessel_i(-v, p, pol);
//T j2 = boost::math::cyl_bessel_i(v, p, pol);
//
// Note that although we can calculate ai from j1 and j2, the accuracy is horrible
// as we're subtracting two very large values, so use the Bessel K relation instead:
//
T aip = -cyl_bessel_k(v, p, pol) * x / (boost::math::constants::root_three<T>() * boost::math::constants::pi<T>());
return aip;
}
}
template <class T, class Policy>
T airy_bi_prime_imp(T x, const Policy& pol)
{
BOOST_MATH_STD_USING
if(x < 0)
{
T p = (-x * sqrt(-x) * 2) / 3;
T v = T(2) / 3;
T j1 = boost::math::cyl_bessel_j(v, p, pol);
T j2 = boost::math::cyl_bessel_j(-v, p, pol);
T aip = -x * (j1 + j2) / constants::root_three<T>();
return aip;
}
else if(fabs(x * x) / 2 < tools::epsilon<T>())
{
T tg = boost::math::tgamma(constants::third<T>(), pol);
T bip = sqrt(boost::math::cbrt(T(3))) / tg;
return bip;
}
else
{
T p = 2 * x * sqrt(x) / 3;
T v = T(2) / 3;
T j1 = boost::math::cyl_bessel_i(-v, p, pol);
T j2 = boost::math::cyl_bessel_i(v, p, pol);
T aip = x * (j1 + j2) / boost::math::constants::root_three<T>();
return aip;
}
}
template <class T, class Policy>
T airy_ai_zero_imp(int m, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
// Handle cases when a negative zero (negative rank) is requested.
if(m < 0)
{
return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%, int)",
"Requested the %1%'th zero, but the rank must be 1 or more !", static_cast<T>(m), pol);
}
// Handle case when the zero'th zero is requested.
if(m == 0U)
{
return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%,%1%)",
"The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
}
// Set up the initial guess for the upcoming root-finding.
const T guess_root = boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess<T>(m);
// Select the maximum allowed iterations based on the number
// of decimal digits in the numeric type T, being at least 12.
const int my_digits10 = static_cast<int>(static_cast<float>(policies::digits<T, Policy>() * 0.301F));
const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2));
boost::uintmax_t iterations_used = iterations_allowed;
// Use a dynamic tolerance because the roots get closer the higher m gets.
T tolerance;
if (m <= 10) { tolerance = T(0.3F); }
else if(m <= 100) { tolerance = T(0.1F); }
else if(m <= 1000) { tolerance = T(0.05F); }
else { tolerance = T(1) / sqrt(T(m)); }
// Perform the root-finding using Newton-Raphson iteration from Boost.Math.
const T am =
boost::math::tools::newton_raphson_iterate(
boost::math::detail::airy_zero::airy_ai_zero_detail::function_object_ai_and_ai_prime<T, Policy>(pol),
guess_root,
T(guess_root - tolerance),
T(guess_root + tolerance),
policies::digits<T, Policy>(),
iterations_used);
static_cast<void>(iterations_used);
return am;
}
template <class T, class Policy>
T airy_bi_zero_imp(int m, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
// Handle cases when a negative zero (negative rank) is requested.
if(m < 0)
{
return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%, int)",
"Requested the %1%'th zero, but the rank must 1 or more !", static_cast<T>(m), pol);
}
// Handle case when the zero'th zero is requested.
if(m == 0U)
{
return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%,%1%)",
"The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
}
// Set up the initial guess for the upcoming root-finding.
const T guess_root = boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess<T>(m);
// Select the maximum allowed iterations based on the number
// of decimal digits in the numeric type T, being at least 12.
const int my_digits10 = static_cast<int>(static_cast<float>(policies::digits<T, Policy>() * 0.301F));
const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2));
boost::uintmax_t iterations_used = iterations_allowed;
// Use a dynamic tolerance because the roots get closer the higher m gets.
T tolerance;
if (m <= 10) { tolerance = T(0.3F); }
else if(m <= 100) { tolerance = T(0.1F); }
else if(m <= 1000) { tolerance = T(0.05F); }
else { tolerance = T(1) / sqrt(T(m)); }
// Perform the root-finding using Newton-Raphson iteration from Boost.Math.
const T bm =
boost::math::tools::newton_raphson_iterate(
boost::math::detail::airy_zero::airy_bi_zero_detail::function_object_bi_and_bi_prime<T, Policy>(pol),
guess_root,
T(guess_root - tolerance),
T(guess_root + tolerance),
policies::digits<T, Policy>(),
iterations_used);
static_cast<void>(iterations_used);
return bm;
}
} // namespace detail
template <class T, class Policy>
inline typename tools::promote_args<T>::type airy_ai(T x, const Policy&)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_ai_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
}
template <class T>
inline typename tools::promote_args<T>::type airy_ai(T x)
{
return airy_ai(x, policies::policy<>());
}
template <class T, class Policy>
inline typename tools::promote_args<T>::type airy_bi(T x, const Policy&)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_bi_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
}
template <class T>
inline typename tools::promote_args<T>::type airy_bi(T x)
{
return airy_bi(x, policies::policy<>());
}
template <class T, class Policy>
inline typename tools::promote_args<T>::type airy_ai_prime(T x, const Policy&)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_ai_prime_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
}
template <class T>
inline typename tools::promote_args<T>::type airy_ai_prime(T x)
{
return airy_ai_prime(x, policies::policy<>());
}
template <class T, class Policy>
inline typename tools::promote_args<T>::type airy_bi_prime(T x, const Policy&)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename tools::promote_args<T>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_bi_prime_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
}
template <class T>
inline typename tools::promote_args<T>::type airy_bi_prime(T x)
{
return airy_bi_prime(x, policies::policy<>());
}
template <class T, class Policy>
inline T airy_ai_zero(int m, const Policy& /*pol*/)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename policies::evaluation<T, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|| ( true == std::numeric_limits<T>::is_specialized
&& false == std::numeric_limits<T>::is_integer),
"Airy value type must be a floating-point type.");
return policies::checked_narrowing_cast<T, Policy>(detail::airy_ai_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_ai_zero<%1%>(unsigned)");
}
template <class T>
inline T airy_ai_zero(int m)
{
return airy_ai_zero<T>(m, policies::policy<>());
}
template <class T, class OutputIterator, class Policy>
inline OutputIterator airy_ai_zero(
int start_index,
unsigned number_of_zeros,
OutputIterator out_it,
const Policy& pol)
{
typedef T result_type;
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|| ( true == std::numeric_limits<T>::is_specialized
&& false == std::numeric_limits<T>::is_integer),
"Airy value type must be a floating-point type.");
for(unsigned i = 0; i < number_of_zeros; ++i)
{
*out_it = boost::math::airy_ai_zero<result_type>(start_index + i, pol);
++out_it;
}
return out_it;
}
template <class T, class OutputIterator>
inline OutputIterator airy_ai_zero(
int start_index,
unsigned number_of_zeros,
OutputIterator out_it)
{
return airy_ai_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
}
template <class T, class Policy>
inline T airy_bi_zero(int m, const Policy& /*pol*/)
{
BOOST_FPU_EXCEPTION_GUARD
typedef typename policies::evaluation<T, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|| ( true == std::numeric_limits<T>::is_specialized
&& false == std::numeric_limits<T>::is_integer),
"Airy value type must be a floating-point type.");
return policies::checked_narrowing_cast<T, Policy>(detail::airy_bi_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_bi_zero<%1%>(unsigned)");
}
template <typename T>
inline T airy_bi_zero(int m)
{
return airy_bi_zero<T>(m, policies::policy<>());
}
template <class T, class OutputIterator, class Policy>
inline OutputIterator airy_bi_zero(
int start_index,
unsigned number_of_zeros,
OutputIterator out_it,
const Policy& pol)
{
typedef T result_type;
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|| ( true == std::numeric_limits<T>::is_specialized
&& false == std::numeric_limits<T>::is_integer),
"Airy value type must be a floating-point type.");
for(unsigned i = 0; i < number_of_zeros; ++i)
{
*out_it = boost::math::airy_bi_zero<result_type>(start_index + i, pol);
++out_it;
}
return out_it;
}
template <class T, class OutputIterator>
inline OutputIterator airy_bi_zero(
int start_index,
unsigned number_of_zeros,
OutputIterator out_it)
{
return airy_bi_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
}
}} // namespaces
#endif // BOOST_MATH_AIRY_HPP

View File

@@ -0,0 +1,112 @@
// boost asinh.hpp header file
// (C) Copyright Eric Ford & Hubert Holin 2001.
// (C) Copyright John Maddock 2008.
// 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)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_ASINH_HPP
#define BOOST_ASINH_HPP
#ifdef _MSC_VER
#pragma once
#endif
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/config.hpp>
#include <boost/math/tools/precision.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/sqrt1pm1.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/constants/constants.hpp>
// This is the inverse of the hyperbolic sine function.
namespace boost
{
namespace math
{
namespace detail{
template<typename T, class Policy>
inline T asinh_imp(const T x, const Policy& pol)
{
BOOST_MATH_STD_USING
if((boost::math::isnan)(x))
{
return policies::raise_domain_error<T>(
"boost::math::asinh<%1%>(%1%)",
"asinh requires a finite argument, but got x = %1%.", x, pol);
}
if (x >= tools::forth_root_epsilon<T>())
{
if (x > 1 / tools::root_epsilon<T>())
{
// http://functions.wolfram.com/ElementaryFunctions/ArcSinh/06/01/06/01/0001/
// approximation by laurent series in 1/x at 0+ order from -1 to 1
return constants::ln_two<T>() + log(x) + 1/ (4 * x * x);
}
else if(x < 0.5f)
{
// As below, but rearranged to preserve digits:
return boost::math::log1p(x + boost::math::sqrt1pm1(x * x, pol), pol);
}
else
{
// http://functions.wolfram.com/ElementaryFunctions/ArcSinh/02/
return( log( x + sqrt(x*x+1) ) );
}
}
else if (x <= -tools::forth_root_epsilon<T>())
{
return(-asinh(-x, pol));
}
else
{
// http://functions.wolfram.com/ElementaryFunctions/ArcSinh/06/01/03/01/0001/
// approximation by taylor series in x at 0 up to order 2
T result = x;
if (abs(x) >= tools::root_epsilon<T>())
{
T x3 = x*x*x;
// approximation by taylor series in x at 0 up to order 4
result -= x3/static_cast<T>(6);
}
return(result);
}
}
}
template<typename T>
inline typename tools::promote_args<T>::type asinh(T x)
{
return boost::math::asinh(x, policies::policy<>());
}
template<typename T, typename Policy>
inline typename tools::promote_args<T>::type asinh(T x, const Policy&)
{
typedef typename tools::promote_args<T>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
detail::asinh_imp(static_cast<value_type>(x), forwarding_policy()),
"boost::math::asinh<%1%>(%1%)");
}
}
}
#endif /* BOOST_ASINH_HPP */

View File

@@ -0,0 +1,123 @@
// boost atanh.hpp header file
// (C) Copyright Hubert Holin 2001.
// (C) Copyright John Maddock 2008.
// 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)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_ATANH_HPP
#define BOOST_ATANH_HPP
#ifdef _MSC_VER
#pragma once
#endif
#include <boost/config/no_tr1/cmath.hpp>
#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>
#include <boost/math/special_functions/log1p.hpp>
// This is the inverse of the hyperbolic tangent function.
namespace boost
{
namespace math
{
namespace detail
{
// This is the main fare
template<typename T, typename Policy>
inline T atanh_imp(const T x, const Policy& pol)
{
BOOST_MATH_STD_USING
static const char* function = "boost::math::atanh<%1%>(%1%)";
if(x < -1)
{
return policies::raise_domain_error<T>(
function,
"atanh requires x >= -1, but got x = %1%.", x, pol);
}
else if(x > 1)
{
return policies::raise_domain_error<T>(
function,
"atanh requires x <= 1, but got x = %1%.", x, pol);
}
else if((boost::math::isnan)(x))
{
return policies::raise_domain_error<T>(
function,
"atanh requires -1 <= x <= 1, but got x = %1%.", x, pol);
}
else if(x < -1 + tools::epsilon<T>())
{
// -Infinity:
return -policies::raise_overflow_error<T>(function, 0, pol);
}
else if(x > 1 - tools::epsilon<T>())
{
// Infinity:
return policies::raise_overflow_error<T>(function, 0, pol);
}
else if(abs(x) >= tools::forth_root_epsilon<T>())
{
// http://functions.wolfram.com/ElementaryFunctions/ArcTanh/02/
if(abs(x) < 0.5f)
return (boost::math::log1p(x, pol) - boost::math::log1p(-x, pol)) / 2;
return(log( (1 + x) / (1 - x) ) / 2);
}
else
{
// http://functions.wolfram.com/ElementaryFunctions/ArcTanh/06/01/03/01/
// approximation by taylor series in x at 0 up to order 2
T result = x;
if (abs(x) >= tools::root_epsilon<T>())
{
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);
}
}
}
template<typename T, typename Policy>
inline typename tools::promote_args<T>::type atanh(T x, const Policy&)
{
typedef typename tools::promote_args<T>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
detail::atanh_imp(static_cast<value_type>(x), forwarding_policy()),
"boost::math::atanh<%1%>(%1%)");
}
template<typename T>
inline typename tools::promote_args<T>::type atanh(T x)
{
return boost::math::atanh(x, policies::policy<>());
}
}
}
#endif /* BOOST_ATANH_HPP */

View File

@@ -0,0 +1,143 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright 2013 Nikhar Agrawal
// Copyright 2013 Christopher Kormanyos
// Copyright 2013 John Maddock
// Copyright 2013 Paul 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)
#ifndef _BOOST_BERNOULLI_B2N_2013_05_30_HPP_
#define _BOOST_BERNOULLI_B2N_2013_05_30_HPP_
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/detail/unchecked_bernoulli.hpp>
#include <boost/math/special_functions/detail/bernoulli_details.hpp>
namespace boost { namespace math {
namespace detail {
template <class T, class OutputIterator, class Policy, int N>
OutputIterator bernoulli_number_imp(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol, const mpl::int_<N>& tag)
{
for(std::size_t i = start; (i <= max_bernoulli_b2n<T>::value) && (i < start + n); ++i)
{
*out = unchecked_bernoulli_imp<T>(i, tag);
++out;
}
for(std::size_t i = (std::max)(static_cast<std::size_t>(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
{
// We must overflow:
*out = (i & 1 ? 1 : -1) * policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(n)", 0, T(i), pol);
++out;
}
return out;
}
template <class T, class OutputIterator, class Policy>
OutputIterator bernoulli_number_imp(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol, const mpl::int_<0>& tag)
{
for(std::size_t i = start; (i <= max_bernoulli_b2n<T>::value) && (i < start + n); ++i)
{
*out = unchecked_bernoulli_imp<T>(i, tag);
++out;
}
//
// Short circuit return so we don't grab the mutex below unless we have to:
//
if(start + n <= max_bernoulli_b2n<T>::value)
return out;
return get_bernoulli_numbers_cache<T, Policy>().copy_bernoulli_numbers(out, start, n, pol);
}
} // namespace detail
template <class T, class Policy>
inline T bernoulli_b2n(const int i, const Policy &pol)
{
typedef mpl::int_<detail::bernoulli_imp_variant<T>::value> tag_type;
if(i < 0)
return policies::raise_domain_error<T>("boost::math::bernoulli_b2n<%1%>", "Index should be >= 0 but got %1%", T(i), pol);
T result = static_cast<T>(0); // The = 0 is just to silence compiler warnings :-(
boost::math::detail::bernoulli_number_imp<T>(&result, static_cast<std::size_t>(i), 1u, pol, tag_type());
return result;
}
template <class T>
inline T bernoulli_b2n(const int i)
{
return boost::math::bernoulli_b2n<T>(i, policies::policy<>());
}
template <class T, class OutputIterator, class Policy>
inline OutputIterator bernoulli_b2n(const int start_index,
const unsigned number_of_bernoullis_b2n,
OutputIterator out_it,
const Policy& pol)
{
typedef mpl::int_<detail::bernoulli_imp_variant<T>::value> tag_type;
if(start_index < 0)
{
*out_it = policies::raise_domain_error<T>("boost::math::bernoulli_b2n<%1%>", "Index should be >= 0 but got %1%", T(start_index), pol);
return ++out_it;
}
return boost::math::detail::bernoulli_number_imp<T>(out_it, start_index, number_of_bernoullis_b2n, pol, tag_type());
}
template <class T, class OutputIterator>
inline OutputIterator bernoulli_b2n(const int start_index,
const unsigned number_of_bernoullis_b2n,
OutputIterator out_it)
{
return boost::math::bernoulli_b2n<T, OutputIterator>(start_index, number_of_bernoullis_b2n, out_it, policies::policy<>());
}
template <class T, class Policy>
inline T tangent_t2n(const int i, const Policy &pol)
{
if(i < 0)
return policies::raise_domain_error<T>("boost::math::tangent_t2n<%1%>", "Index should be >= 0 but got %1%", T(i), pol);
T result;
boost::math::detail::get_bernoulli_numbers_cache<T, Policy>().copy_tangent_numbers(&result, i, 1, pol);
return result;
}
template <class T>
inline T tangent_t2n(const int i)
{
return boost::math::tangent_t2n<T>(i, policies::policy<>());
}
template <class T, class OutputIterator, class Policy>
inline OutputIterator tangent_t2n(const int start_index,
const unsigned number_of_tangent_t2n,
OutputIterator out_it,
const Policy& pol)
{
if(start_index < 0)
{
*out_it = policies::raise_domain_error<T>("boost::math::tangent_t2n<%1%>", "Index should be >= 0 but got %1%", T(start_index), pol);
return ++out_it;
}
return boost::math::detail::get_bernoulli_numbers_cache<T, Policy>().copy_tangent_numbers(out_it, start_index, number_of_tangent_t2n, pol);
}
template <class T, class OutputIterator>
inline OutputIterator tangent_t2n(const int start_index,
const unsigned number_of_tangent_t2n,
OutputIterator out_it)
{
return boost::math::tangent_t2n<T, OutputIterator>(start_index, number_of_tangent_t2n, out_it, policies::policy<>());
}
} } // namespace boost::math
#endif // _BOOST_BERNOULLI_B2N_2013_05_30_HPP_

View File

@@ -0,0 +1,762 @@
// Copyright (c) 2007, 2013 John Maddock
// Copyright Christopher Kormanyos 2013.
// 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
#ifdef _MSC_VER
# pragma once
#endif
#include <limits>
#include <boost/math/special_functions/math_fwd.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_jy_zero.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/detail/iconv.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/special_functions/trunc.hpp>
#include <boost/math/special_functions/round.hpp>
#include <boost/math/tools/rational.hpp>
#include <boost/math/tools/promotion.hpp>
#include <boost/math/tools/series.hpp>
#include <boost/math/tools/roots.hpp>
namespace boost{ namespace math{
namespace detail{
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;
if(v + 3 > max_factorial<T>::value)
{
term = v * log(mult) - boost::math::lgamma(v+1+T(0.5f), Policy());
term = exp(term);
}
else
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 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>();
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
T zero = 0;
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
#else
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
#endif
policies::check_series_iterations<T>("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, T(-x), t, pol);
if(iround(v, pol) & 1)
r = -r;
return r;
}
else
return policies::raise_domain_error<T>(
function,
"Got x = %1%, but we need x >= 0", 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.
int ival = detail::iconv(v, pol);
// If v is an integer, use the integer recursion
// method, both that and Steeds method are O(v):
if((0 == v - ival))
{
return bessel_jn(ival, 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
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);
//
// Special case for x == 0:
//
if(x == 0)
return 0;
//
// 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(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, T(-x), pol);
if(iround(v, pol) & 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) ? static_cast<T>(1) : static_cast<T>(0);
}
if(v == 0.5f)
{
// common special case, note try and avoid overflow in exp(x):
if(x >= tools::log_max_value<T>())
{
T e = exp(x / 2);
return e * (e / sqrt(2 * x * constants::pi<T>()));
}
return sqrt(2 / (x * constants::pi<T>())) * sinh(x);
}
if(policies::digits<T, Policy>() <= 113)
{
if(v == 0)
{
return bessel_i0(x);
}
if(v == 1)
{
return bessel_i1(x);
}
}
if((v > 0) && (x / v < 0.25))
return bessel_i_small_z_series(v, x, pol);
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(itrunc(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%)";
BOOST_MATH_INSTRUMENT_VARIABLE(v);
BOOST_MATH_INSTRUMENT_VARIABLE(x);
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
BOOST_MATH_INSTRUMENT_VARIABLE(v);
BOOST_MATH_INSTRUMENT_VARIABLE(x);
if(floor(v) == v)
{
T r = bessel_yn(itrunc(v, pol), x, pol);
BOOST_MATH_INSTRUMENT_VARIABLE(r);
return r;
}
T r = cyl_neumann_imp<T>(v, x, bessel_no_int_tag(), pol);
BOOST_MATH_INSTRUMENT_VARIABLE(r);
return r;
}
template <class T, class Policy>
inline T cyl_neumann_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
{
return bessel_yn(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(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;
}
template <class T, class Policy>
inline T cyl_bessel_j_zero_imp(T v, int m, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std names, needed for floor.
static const char* function = "boost::math::cyl_bessel_j_zero<%1%>(%1%, int)";
const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
// Handle non-finite order.
if (!(boost::math::isfinite)(v) )
{
return policies::raise_domain_error<T>(function, "Order argument is %1%, but must be finite >= 0 !", v, pol);
}
// Handle negative rank.
if(m < 0)
{
// Zeros of Jv(x) with negative rank are not defined and requesting one raises a domain error.
return policies::raise_domain_error<T>(function, "Requested the %1%'th zero, but the rank must be positive !", static_cast<T>(m), pol);
}
// Get the absolute value of the order.
const bool order_is_negative = (v < 0);
const T vv((!order_is_negative) ? v : T(-v));
// Check if the order is very close to zero or very close to an integer.
const bool order_is_zero = (vv < half_epsilon);
const bool order_is_integer = ((vv - floor(vv)) < half_epsilon);
if(m == 0)
{
if(order_is_zero)
{
// The zero'th zero of J0(x) is not defined and requesting it raises a domain error.
return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of J0, but the rank must be > 0 !", static_cast<T>(m), pol);
}
// The zero'th zero of Jv(x) for v < 0 is not defined
// unless the order is a negative integer.
if(order_is_negative && (!order_is_integer))
{
// For non-integer, negative order, requesting the zero'th zero raises a domain error.
return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of Jv for negative, non-integer order, but the rank must be > 0 !", static_cast<T>(m), pol);
}
// The zero'th zero does exist and its value is zero.
return T(0);
}
// Set up the initial guess for the upcoming root-finding.
// If the order is a negative integer, then use the corresponding
// positive integer for the order.
const T guess_root = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess<T, Policy>((order_is_integer ? vv : v), m, pol);
// Select the maximum allowed iterations from the policy.
boost::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U));
// Perform the root-finding using Newton-Raphson iteration from Boost.Math.
const T jvm =
boost::math::tools::newton_raphson_iterate(
boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::function_object_jv_and_jv_prime<T, Policy>((order_is_integer ? vv : v), order_is_zero, pol),
guess_root,
T(guess_root - delta_lo),
T(guess_root + 0.2F),
policies::digits<T, Policy>(),
number_of_iterations);
if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
{
return policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time:"
" Current best guess is %1%", jvm, Policy());
}
return jvm;
}
template <class T, class Policy>
inline T cyl_neumann_zero_imp(T v, int m, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std names, needed for floor.
static const char* function = "boost::math::cyl_neumann_zero<%1%>(%1%, int)";
// Handle non-finite order.
if (!(boost::math::isfinite)(v) )
{
return policies::raise_domain_error<T>(function, "Order argument is %1%, but must be finite >= 0 !", v, pol);
}
// Handle negative rank.
if(m < 0)
{
return policies::raise_domain_error<T>(function, "Requested the %1%'th zero, but the rank must be positive !", static_cast<T>(m), pol);
}
const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
// Get the absolute value of the order.
const bool order_is_negative = (v < 0);
const T vv((!order_is_negative) ? v : T(-v));
const bool order_is_integer = ((vv - floor(vv)) < half_epsilon);
// For negative integers, use reflection to positive integer order.
if(order_is_negative && order_is_integer)
return boost::math::detail::cyl_neumann_zero_imp(vv, m, pol);
// Check if the order is very close to a negative half-integer.
const T delta_half_integer(vv - (floor(vv) + 0.5F));
const bool order_is_negative_half_integer =
(order_is_negative && ((delta_half_integer > -half_epsilon) && (delta_half_integer < +half_epsilon)));
// The zero'th zero of Yv(x) for v < 0 is not defined
// unless the order is a negative integer.
if((m == 0) && (!order_is_negative_half_integer))
{
// For non-integer, negative order, requesting the zero'th zero raises a domain error.
return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of Yv for negative, non-half-integer order, but the rank must be > 0 !", static_cast<T>(m), pol);
}
// For negative half-integers, use the corresponding
// spherical Bessel function of positive half-integer order.
if(order_is_negative_half_integer)
return boost::math::detail::cyl_bessel_j_zero_imp(vv, m, pol);
// Set up the initial guess for the upcoming root-finding.
// If the order is a negative integer, then use the corresponding
// positive integer for the order.
const T guess_root = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess<T, Policy>(v, m, pol);
// Select the maximum allowed iterations from the policy.
boost::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U));
// Perform the root-finding using Newton-Raphson iteration from Boost.Math.
const T yvm =
boost::math::tools::newton_raphson_iterate(
boost::math::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv_and_yv_prime<T, Policy>(v, pol),
guess_root,
T(guess_root - delta_lo),
T(guess_root + 0.2F),
policies::digits<T, Policy>(),
number_of_iterations);
if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
{
return policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time:"
" Current best guess is %1%", yvm, Policy());
}
return yvm;
}
} // 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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_bessel_j_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_i_imp<value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "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_tag128 tag_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_k_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_neumann_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "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<>());
}
template <class T, class Policy>
inline typename detail::bessel_traits<T, T, Policy>::result_type cyl_bessel_j_zero(T v, int m, 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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|| ( true == std::numeric_limits<T>::is_specialized
&& false == std::numeric_limits<T>::is_integer),
"Order must be a floating-point type.");
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_zero_imp<value_type>(v, m, forwarding_policy()), "boost::math::cyl_bessel_j_zero<%1%>(%1%,%1%)");
}
template <class T>
inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_bessel_j_zero(T v, int m)
{
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|| ( true == std::numeric_limits<T>::is_specialized
&& false == std::numeric_limits<T>::is_integer),
"Order must be a floating-point type.");
return cyl_bessel_j_zero<T, policies::policy<> >(v, m, policies::policy<>());
}
template <class T, class OutputIterator, class Policy>
inline OutputIterator cyl_bessel_j_zero(T v,
int start_index,
unsigned number_of_zeros,
OutputIterator out_it,
const Policy& pol)
{
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|| ( true == std::numeric_limits<T>::is_specialized
&& false == std::numeric_limits<T>::is_integer),
"Order must be a floating-point type.");
for(int i = 0; i < static_cast<int>(number_of_zeros); ++i)
{
*out_it = boost::math::cyl_bessel_j_zero(v, start_index + i, pol);
++out_it;
}
return out_it;
}
template <class T, class OutputIterator>
inline OutputIterator cyl_bessel_j_zero(T v,
int start_index,
unsigned number_of_zeros,
OutputIterator out_it)
{
return cyl_bessel_j_zero(v, start_index, number_of_zeros, out_it, policies::policy<>());
}
template <class T, class Policy>
inline typename detail::bessel_traits<T, T, Policy>::result_type cyl_neumann_zero(T v, int m, 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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|| ( true == std::numeric_limits<T>::is_specialized
&& false == std::numeric_limits<T>::is_integer),
"Order must be a floating-point type.");
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_zero_imp<value_type>(v, m, forwarding_policy()), "boost::math::cyl_neumann_zero<%1%>(%1%,%1%)");
}
template <class T>
inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_neumann_zero(T v, int m)
{
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|| ( true == std::numeric_limits<T>::is_specialized
&& false == std::numeric_limits<T>::is_integer),
"Order must be a floating-point type.");
return cyl_neumann_zero<T, policies::policy<> >(v, m, policies::policy<>());
}
template <class T, class OutputIterator, class Policy>
inline OutputIterator cyl_neumann_zero(T v,
int start_index,
unsigned number_of_zeros,
OutputIterator out_it,
const Policy& pol)
{
BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|| ( true == std::numeric_limits<T>::is_specialized
&& false == std::numeric_limits<T>::is_integer),
"Order must be a floating-point type.");
for(int i = 0; i < static_cast<int>(number_of_zeros); ++i)
{
*out_it = boost::math::cyl_neumann_zero(v, start_index + i, pol);
++out_it;
}
return out_it;
}
template <class T, class OutputIterator>
inline OutputIterator cyl_neumann_zero(T v,
int start_index,
unsigned number_of_zeros,
OutputIterator out_it)
{
return cyl_neumann_zero(v, start_index, number_of_zeros, out_it, policies::policy<>());
}
} // namespace math
} // namespace boost
#endif // BOOST_MATH_BESSEL_HPP

View File

@@ -0,0 +1,359 @@
// Copyright (c) 2013 Anton Bikineev
// 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_DERIVATIVES_HPP
#define BOOST_MATH_BESSEL_DERIVATIVES_HPP
#ifdef _MSC_VER
# pragma once
#endif
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/bessel.hpp>
#include <boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp>
#include <boost/math/special_functions/detail/bessel_jy_derivatives_series.hpp>
#include <boost/math/special_functions/detail/bessel_derivatives_linear.hpp>
namespace boost{ namespace math{
namespace detail{
template <class Tag, class T, class Policy>
inline T cyl_bessel_j_prime_imp(T v, T x, const Policy& pol)
{
static const char* const function = "boost::math::cyl_bessel_j_prime<%1%>(%1%,%1%)";
BOOST_MATH_STD_USING
//
// Prevent complex result:
//
if (x < 0 && floor(v) != v)
return boost::math::policies::raise_domain_error<T>(
function,
"Got x = %1%, but function requires x >= 0", x, pol);
//
// Special cases for x == 0:
//
if (x == 0)
{
if (v == 1)
return 0.5;
else if (v == -1)
return -0.5;
else if (floor(v) == v || v > 1)
return 0;
else return boost::math::policies::raise_domain_error<T>(
function,
"Got x = %1%, but function is indeterminate for this order", x, pol);
}
//
// Special case for large x: use asymptotic expansion:
//
if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x))
return boost::math::detail::asymptotic_bessel_j_derivative_large_x_2(v, x);
//
// Special case for small x: use Taylor series:
//
if ((abs(x) < 5) || (abs(v) > x * x / 4))
{
bool inversed = false;
if (floor(v) == v && v < 0)
{
v = -v;
if (itrunc(v, pol) & 1)
inversed = true;
}
T r = boost::math::detail::bessel_j_derivative_small_z_series(v, x, pol);
return inversed ? T(-r) : r;
}
//
// Special case for v == 0:
//
if (v == 0)
return -boost::math::detail::cyl_bessel_j_imp<T>(1, x, Tag(), pol);
//
// Default case:
//
return boost::math::detail::bessel_j_derivative_linear(v, x, Tag(), pol);
}
template <class T, class Policy>
inline T sph_bessel_j_prime_imp(unsigned v, T x, const Policy& pol)
{
static const char* const function = "boost::math::sph_bessel_prime<%1%>(%1%,%1%)";
//
// Prevent complex result:
//
if (x < 0)
return boost::math::policies::raise_domain_error<T>(
function,
"Got x = %1%, but function requires x >= 0.", x, pol);
//
// Special case for v == 0:
//
if (v == 0)
return (x == 0) ? boost::math::policies::raise_overflow_error<T>(function, 0, pol)
: static_cast<T>(-boost::math::detail::sph_bessel_j_imp<T>(1, x, pol));
//
// Special case for x == 0 and v > 0:
//
if (x == 0)
return boost::math::policies::raise_domain_error<T>(
function,
"Got x = %1%, but function is indeterminate for this order", x, pol);
//
// Default case:
//
return boost::math::detail::sph_bessel_j_derivative_linear(v, x, pol);
}
template <class T, class Policy>
inline T cyl_bessel_i_prime_imp(T v, T x, const Policy& pol)
{
static const char* const function = "boost::math::cyl_bessel_i_prime<%1%>(%1%,%1%)";
BOOST_MATH_STD_USING
//
// Prevent complex result:
//
if (x < 0 && floor(v) != v)
return boost::math::policies::raise_domain_error<T>(
function,
"Got x = %1%, but function requires x >= 0", x, pol);
//
// Special cases for x == 0:
//
if (x == 0)
{
if (v == 1 || v == -1)
return 0.5;
else if (floor(v) == v || v > 1)
return 0;
else return boost::math::policies::raise_domain_error<T>(
function,
"Got x = %1%, but function is indeterminate for this order", x, pol);
}
//
// Special case for v == 0:
//
if (v == 0)
return boost::math::detail::cyl_bessel_i_imp<T>(1, x, pol);
//
// Default case:
//
return boost::math::detail::bessel_i_derivative_linear(v, x, pol);
}
template <class Tag, class T, class Policy>
inline T cyl_bessel_k_prime_imp(T v, T x, const Policy& pol)
{
//
// Prevent complex and indeterminate results:
//
if (x <= 0)
return boost::math::policies::raise_domain_error<T>(
"boost::math::cyl_bessel_k_prime<%1%>(%1%,%1%)",
"Got x = %1%, but function requires x > 0", x, pol);
//
// Special case for v == 0:
//
if (v == 0)
return -boost::math::detail::cyl_bessel_k_imp<T>(1, x, Tag(), pol);
//
// Default case:
//
return boost::math::detail::bessel_k_derivative_linear(v, x, Tag(), pol);
}
template <class Tag, class T, class Policy>
inline T cyl_neumann_prime_imp(T v, T x, const Policy& pol)
{
BOOST_MATH_STD_USING
//
// Prevent complex and indeterminate results:
//
if (x <= 0)
return boost::math::policies::raise_domain_error<T>(
"boost::math::cyl_neumann_prime<%1%>(%1%,%1%)",
"Got x = %1%, but function requires x > 0", x, pol);
//
// Special case for large x: use asymptotic expansion:
//
if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x))
return boost::math::detail::asymptotic_bessel_y_derivative_large_x_2(v, x);
//
// Special case for small x: use Taylor series:
//
if (v > 0 && floor(v) != v)
{
const T eps = boost::math::policies::get_epsilon<T, Policy>();
if (log(eps / 2) > v * log((x * x) / (v * 4)))
return boost::math::detail::bessel_y_derivative_small_z_series(v, x, pol);
}
//
// Special case for v == 0:
//
if (v == 0)
return -boost::math::detail::cyl_neumann_imp<T>(1, x, Tag(), pol);
//
// Default case:
//
return boost::math::detail::bessel_y_derivative_linear(v, x, Tag(), pol);
}
template <class T, class Policy>
inline T sph_neumann_prime_imp(unsigned v, T x, const Policy& pol)
{
//
// Prevent complex and indeterminate result:
//
if (x <= 0)
return boost::math::policies::raise_domain_error<T>(
"boost::math::sph_neumann_prime<%1%>(%1%,%1%)",
"Got x = %1%, but function requires x > 0.", x, pol);
//
// Special case for v == 0:
//
if (v == 0)
return -boost::math::detail::sph_neumann_imp<T>(1, x, pol);
//
// Default case:
//
return boost::math::detail::sph_neumann_derivative_linear(v, x, pol);
}
} // namespace detail
template <class T1, class T2, class Policy>
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j_prime(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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_prime_imp<tag_type, value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_j_prime<%1%,%1%>(%1%,%1%)");
}
template <class T1, class T2>
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_j_prime(T1 v, T2 x)
{
return cyl_bessel_j_prime(v, x, policies::policy<>());
}
template <class T, class Policy>
inline typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel_prime(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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_bessel_j_prime_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_bessel_j_prime<%1%>(%1%,%1%)");
}
template <class T>
inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_bessel_prime(unsigned v, T x)
{
return sph_bessel_prime(v, x, policies::policy<>());
}
template <class T1, class T2, class Policy>
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i_prime(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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_i_prime_imp<value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_i_prime<%1%>(%1%,%1%)");
}
template <class T1, class T2>
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_i_prime(T1 v, T2 x)
{
return cyl_bessel_i_prime(v, x, policies::policy<>());
}
template <class T1, class T2, class Policy>
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k_prime(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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_k_prime_imp<tag_type, value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_k_prime<%1%,%1%>(%1%,%1%)");
}
template <class T1, class T2>
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_k_prime(T1 v, T2 x)
{
return cyl_bessel_k_prime(v, x, policies::policy<>());
}
template <class T1, class T2, class Policy>
inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann_prime(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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_prime_imp<tag_type, value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_neumann_prime<%1%,%1%>(%1%,%1%)");
}
template <class T1, class T2>
inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_neumann_prime(T1 v, T2 x)
{
return cyl_neumann_prime(v, x, policies::policy<>());
}
template <class T, class Policy>
inline typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann_prime(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;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_neumann_prime_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_neumann_prime<%1%>(%1%,%1%)");
}
template <class T>
inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_neumann_prime(unsigned v, T x)
{
return sph_neumann_prime(v, x, policies::policy<>());
}
} // namespace math
} // namespace boost
#endif // BOOST_MATH_BESSEL_DERIVATIVES_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
// 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
#ifdef _MSC_VER
#pragma once
#endif
#include <boost/math/special_functions/math_fwd.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_STATIC_ASSERT(!boost::is_integral<T>::value);
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%.",
static_cast<T>(k), pol);
T result;
if((k == 0) || (k == n))
return static_cast<T>(1);
if((k == 1) || (k == n-1))
return static_cast<T>(n);
if(n <= max_factorial<T>::value)
{
// Use fast table lookup:
result = unchecked_factorial<T>(n);
result /= unchecked_factorial<T>(n-k);
result /= unchecked_factorial<T>(k);
}
else
{
// Use the beta function:
if(k < n - k)
result = k * beta(static_cast<T>(k), static_cast<T>(n-k+1), pol);
else
result = (n - k) * beta(static_cast<T>(k+1), static_cast<T>(n-k), pol);
if(result == 0)
return policies::raise_overflow_error<T>(function, 0, pol);
result = 1 / result;
}
// convert to nearest integer:
return ceil(result - 0.5f);
}
//
// Type float can only store the first 35 factorials, in order to
// increase the chance that we can use a table driven implementation
// we'll promote to double:
//
template <>
inline float binomial_coefficient<float, policies::policy<> >(unsigned n, unsigned k, const policies::policy<>& pol)
{
return policies::checked_narrowing_cast<float, policies::policy<> >(binomial_coefficient<double>(n, k, pol), "boost::math::binomial_coefficient<%1%>(unsigned,unsigned)");
}
template <class T>
inline T binomial_coefficient(unsigned n, unsigned k)
{
return binomial_coefficient<T>(n, k, policies::policy<>());
}
} // namespace math
} // namespace boost
#endif // BOOST_MATH_SF_BINOMIAL_HPP

View File

@@ -0,0 +1,179 @@
// (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
#ifdef _MSC_VER
#pragma once
#endif
#include <boost/math/tools/rational.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/mpl/divides.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_convertible.hpp>
namespace boost{ namespace math{
namespace detail
{
struct big_int_type
{
operator boost::uintmax_t()const;
};
template <class T>
struct largest_cbrt_int_type
{
typedef typename mpl::if_<
boost::is_convertible<big_int_type, T>,
boost::uintmax_t,
unsigned int
>::type type;
};
template <class T, class Policy>
T cbrt_imp(T z, const Policy& pol)
{
BOOST_MATH_STD_USING
//
// cbrt approximation for z in the range [0.5,1]
// It's hard to say what number of terms gives the optimum
// trade off between precision and performance, this seems
// to be about the best for double precision.
//
// Maximum Deviation Found: 1.231e-006
// Expected Error Term: -1.231e-006
// Maximum Relative Change in Control Points: 5.982e-004
//
static const T P[] = {
static_cast<T>(0.37568269008611818),
static_cast<T>(1.3304968705558024),
static_cast<T>(-1.4897101632445036),
static_cast<T>(1.2875573098219835),
static_cast<T>(-0.6398703759826468),
static_cast<T>(0.13584489959258635),
};
static const T correction[] = {
static_cast<T>(0.62996052494743658238360530363911), // 2^-2/3
static_cast<T>(0.79370052598409973737585281963615), // 2^-1/3
static_cast<T>(1),
static_cast<T>(1.2599210498948731647672106072782), // 2^1/3
static_cast<T>(1.5874010519681994747517056392723), // 2^2/3
};
if((boost::math::isinf)(z) || (z == 0))
return z;
if(!(boost::math::isfinite)(z))
{
return policies::raise_domain_error("boost::math::cbrt<%1%>(%1%)", "Argument to function must be finite but got %1%.", z, pol);
}
int i_exp, sign(1);
if(z < 0)
{
z = -z;
sign = -sign;
}
T guess = frexp(z, &i_exp);
int original_i_exp = i_exp; // save for later
guess = tools::evaluate_polynomial(P, guess);
int i_exp3 = i_exp / 3;
typedef typename largest_cbrt_int_type<T>::type shift_type;
BOOST_STATIC_ASSERT( ::std::numeric_limits<shift_type>::radix == 2);
if(abs(i_exp3) < std::numeric_limits<shift_type>::digits)
{
if(i_exp3 > 0)
guess *= shift_type(1u) << i_exp3;
else
guess /= shift_type(1u) << -i_exp3;
}
else
{
guess = ldexp(guess, i_exp3);
}
i_exp %= 3;
guess *= correction[i_exp + 2];
//
// Now inline Halley iteration.
// We do this here rather than calling tools::halley_iterate since we can
// simplify the expressions algebraically, and don't need most of the error
// checking of the boilerplate version as we know in advance that the function
// is well behaved...
//
typedef typename policies::precision<T, Policy>::type prec;
typedef typename mpl::divides<prec, mpl::int_<3> >::type prec3;
typedef typename mpl::plus<prec3, mpl::int_<3> >::type new_prec;
typedef typename policies::normalise<Policy, policies::digits2<new_prec::value> >::type new_policy;
//
// Epsilon calculation uses compile time arithmetic when it's available for type T,
// otherwise uses ldexp to calculate at runtime:
//
T eps = (new_prec::value > 3) ? policies::get_epsilon<T, new_policy>() : ldexp(T(1), -2 - tools::digits<T>() / 3);
T diff;
if(original_i_exp < std::numeric_limits<T>::max_exponent - 3)
{
//
// Safe from overflow, use the fast method:
//
do
{
T g3 = guess * guess * guess;
diff = (g3 + z + z) / (g3 + g3 + z);
guess *= diff;
}
while(fabs(1 - diff) > eps);
}
else
{
//
// Either we're ready to overflow, or we can't tell because numeric_limits isn't
// available for type T:
//
do
{
T g2 = guess * guess;
diff = (g2 - z / guess) / (2 * guess + z / g2);
guess -= diff;
}
while((guess * eps) < fabs(diff));
}
return sign * guess;
}
} // 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;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
return static_cast<result_type>(detail::cbrt_imp(value_type(z), pol));
}
template <class T>
inline typename tools::promote_args<T>::type cbrt(T z)
{
return cbrt(z, policies::policy<>());
}
} // namespace math
} // namespace boost
#endif // BOOST_MATH_SF_CBRT_HPP

View File

@@ -0,0 +1,82 @@
// 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
#ifdef _MSC_VER
#pragma once
#endif
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/math/tools/config.hpp>
#include <boost/math/special_functions/trunc.hpp>
#include <boost/math/tools/promotion.hpp>
#include <boost/math/constants/constants.hpp>
namespace boost{ namespace math{ namespace detail{
template <class T, class Policy>
T cos_pi_imp(T x, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std names
// cos of pi*x:
bool invert = false;
if(fabs(x) < 0.25)
return cos(constants::pi<T>() * x);
if(x < 0)
{
x = -x;
}
T rem = floor(x);
if(itrunc(rem, pol) & 1)
invert = !invert;
rem = x - rem;
if(rem > 0.5f)
{
rem = 1 - rem;
invert = !invert;
}
if(rem == 0.5f)
return 0;
if(rem > 0.25f)
{
rem = 0.5f - rem;
rem = sin(constants::pi<T>() * rem);
}
else
rem = cos(constants::pi<T>() * rem);
return invert ? T(-rem) : rem;
}
} // namespace detail
template <class T, class Policy>
inline typename tools::promote_args<T>::type cos_pi(T x, const Policy&)
{
typedef typename tools::promote_args<T>::type result_type;
typedef typename policies::evaluation<result_type, Policy>::type value_type;
typedef typename policies::normalise<
Policy,
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, forwarding_policy>(boost::math::detail::cos_pi_imp<value_type>(x, forwarding_policy()), "cos_pi");
}
template <class T>
inline typename tools::promote_args<T>::type cos_pi(T x)
{
return boost::math::cos_pi(x, policies::policy<>());
}
} // namespace math
} // namespace boost
#endif

View File

@@ -0,0 +1,160 @@
// Copyright (c) 2013 Christopher Kormanyos
// 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 work is based on an earlier work:
// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations",
// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469
//
// This header contains implementation details for estimating the zeros
// of the Airy functions airy_ai and airy_bi on the negative real axis.
//
#ifndef _AIRY_AI_BI_ZERO_2013_01_20_HPP_
#define _AIRY_AI_BI_ZERO_2013_01_20_HPP_
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/cbrt.hpp>
namespace boost { namespace math {
namespace detail
{
// Forward declarations of the needed Airy function implementations.
template <class T, class Policy>
T airy_ai_imp(T x, const Policy& pol);
template <class T, class Policy>
T airy_bi_imp(T x, const Policy& pol);
template <class T, class Policy>
T airy_ai_prime_imp(T x, const Policy& pol);
template <class T, class Policy>
T airy_bi_prime_imp(T x, const Policy& pol);
namespace airy_zero
{
template<class T>
T equation_as_10_4_105(const T& z)
{
const T one_over_z (T(1) / z);
const T one_over_z_squared(one_over_z * one_over_z);
const T z_pow_third (boost::math::cbrt(z));
const T z_pow_two_thirds(z_pow_third * z_pow_third);
// Implement the top line of Eq. 10.4.105.
const T fz(z_pow_two_thirds * ((((( + (T(162375596875.0) / 334430208UL)
* one_over_z_squared - ( T(108056875.0) / 6967296UL))
* one_over_z_squared + ( T(77125UL) / 82944UL))
* one_over_z_squared - ( T(5U) / 36U))
* one_over_z_squared + ( T(5U) / 48U))
* one_over_z_squared + (1)));
return fz;
}
namespace airy_ai_zero_detail
{
template<class T>
T initial_guess(const int m)
{
T guess;
switch(m)
{
case 0: { guess = T(0); break; }
case 1: { guess = T(-2.33810741045976703849); break; }
case 2: { guess = T(-4.08794944413097061664); break; }
case 3: { guess = T(-5.52055982809555105913); break; }
case 4: { guess = T(-6.78670809007175899878); break; }
case 5: { guess = T(-7.94413358712085312314); break; }
case 6: { guess = T(-9.02265085334098038016); break; }
case 7: { guess = T(-10.0401743415580859306); break; }
case 8: { guess = T(-11.0085243037332628932); break; }
case 9: { guess = T(-11.9360155632362625170); break; }
case 10:{ guess = T(-12.8287767528657572004); break; }
default:
{
const T t(((boost::math::constants::pi<T>() * 3) * ((T(m) * 4) - 1)) / 8);
guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t);
break;
}
}
return guess;
}
template<class T, class Policy>
class function_object_ai_and_ai_prime
{
public:
function_object_ai_and_ai_prime(const Policy pol) : my_pol(pol) { }
boost::math::tuple<T, T> operator()(const T& x) const
{
// Return a tuple containing both Ai(x) and Ai'(x).
return boost::math::make_tuple(
boost::math::detail::airy_ai_imp (x, my_pol),
boost::math::detail::airy_ai_prime_imp(x, my_pol));
}
private:
const Policy& my_pol;
const function_object_ai_and_ai_prime& operator=(const function_object_ai_and_ai_prime&);
};
} // namespace airy_ai_zero_detail
namespace airy_bi_zero_detail
{
template<class T>
T initial_guess(const int m)
{
T guess;
switch(m)
{
case 0: { guess = T(0); break; }
case 1: { guess = T(-1.17371322270912792492); break; }
case 2: { guess = T(-3.27109330283635271568); break; }
case 3: { guess = T(-4.83073784166201593267); break; }
case 4: { guess = T(-6.16985212831025125983); break; }
case 5: { guess = T(-7.37676207936776371360); break; }
case 6: { guess = T(-8.49194884650938801345); break; }
case 7: { guess = T(-9.53819437934623888663); break; }
case 8: { guess = T(-10.5299135067053579244); break; }
case 9: { guess = T(-11.4769535512787794379); break; }
case 10: { guess = T(-12.3864171385827387456); break; }
default:
{
const T t(((boost::math::constants::pi<T>() * 3) * ((T(m) * 4) - 3)) / 8);
guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t);
break;
}
}
return guess;
}
template<class T, class Policy>
class function_object_bi_and_bi_prime
{
public:
function_object_bi_and_bi_prime(const Policy pol) : my_pol(pol) { }
boost::math::tuple<T, T> operator()(const T& x) const
{
// Return a tuple containing both Bi(x) and Bi'(x).
return boost::math::make_tuple(
boost::math::detail::airy_bi_imp (x, my_pol),
boost::math::detail::airy_bi_prime_imp(x, my_pol));
}
private:
const Policy& my_pol;
const function_object_bi_and_bi_prime& operator=(const function_object_bi_and_bi_prime&);
};
} // namespace airy_bi_zero_detail
} // namespace airy_zero
} // namespace detail
} // namespace math
} // namespaces boost
#endif // _AIRY_AI_BI_ZERO_2013_01_20_HPP_

View File

@@ -0,0 +1,712 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright 2013 John Maddock
// 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)
#ifndef BOOST_MATH_BERNOULLI_DETAIL_HPP
#define BOOST_MATH_BERNOULLI_DETAIL_HPP
#include <boost/config.hpp>
#include <boost/detail/lightweight_mutex.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/math/tools/toms748_solve.hpp>
#include <vector>
#ifdef BOOST_HAS_THREADS
#ifndef BOOST_NO_CXX11_HDR_ATOMIC
# include <atomic>
# define BOOST_MATH_ATOMIC_NS std
#if ATOMIC_INT_LOCK_FREE == 2
typedef std::atomic<int> atomic_counter_type;
typedef int atomic_integer_type;
#elif ATOMIC_SHORT_LOCK_FREE == 2
typedef std::atomic<short> atomic_counter_type;
typedef short atomic_integer_type;
#elif ATOMIC_LONG_LOCK_FREE == 2
typedef std::atomic<long> atomic_counter_type;
typedef long atomic_integer_type;
#elif ATOMIC_LLONG_LOCK_FREE == 2
typedef std::atomic<long long> atomic_counter_type;
typedef long long atomic_integer_type;
#else
# define BOOST_MATH_NO_ATOMIC_INT
#endif
#else // BOOST_NO_CXX11_HDR_ATOMIC
//
// We need Boost.Atomic, but on any platform that supports auto-linking we do
// not need to link against a separate library:
//
#define BOOST_ATOMIC_NO_LIB
#include <boost/atomic.hpp>
# define BOOST_MATH_ATOMIC_NS boost
namespace boost{ namespace math{ namespace detail{
//
// We need a type to use as an atomic counter:
//
#if BOOST_ATOMIC_INT_LOCK_FREE == 2
typedef boost::atomic<int> atomic_counter_type;
typedef int atomic_integer_type;
#elif BOOST_ATOMIC_SHORT_LOCK_FREE == 2
typedef boost::atomic<short> atomic_counter_type;
typedef short atomic_integer_type;
#elif BOOST_ATOMIC_LONG_LOCK_FREE == 2
typedef boost::atomic<long> atomic_counter_type;
typedef long atomic_integer_type;
#elif BOOST_ATOMIC_LLONG_LOCK_FREE == 2
typedef boost::atomic<long long> atomic_counter_type;
typedef long long atomic_integer_type;
#else
# define BOOST_MATH_NO_ATOMIC_INT
#endif
}}} // namespaces
#endif // BOOST_NO_CXX11_HDR_ATOMIC
#endif // BOOST_HAS_THREADS
namespace boost{ namespace math{ namespace detail{
//
// Asymptotic expansion for B2n due to
// Luschny LogB3 formula (http://www.luschny.de/math/primes/bernincl.html)
//
template <class T, class Policy>
T b2n_asymptotic(int n)
{
BOOST_MATH_STD_USING
const T nx = static_cast<T>(n);
const T nx2(nx * nx);
const T approximate_log_of_bernoulli_bn =
((boost::math::constants::half<T>() + nx) * log(nx))
+ ((boost::math::constants::half<T>() - nx) * log(boost::math::constants::pi<T>()))
+ (((T(3) / 2) - nx) * boost::math::constants::ln_two<T>())
+ ((nx * (T(2) - (nx2 * 7) * (1 + ((nx2 * 30) * ((nx2 * 12) - 1))))) / (((nx2 * nx2) * nx2) * 2520));
return ((n / 2) & 1 ? 1 : -1) * (approximate_log_of_bernoulli_bn > tools::log_max_value<T>()
? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, nx, Policy())
: static_cast<T>(exp(approximate_log_of_bernoulli_bn)));
}
template <class T, class Policy>
T t2n_asymptotic(int n)
{
BOOST_MATH_STD_USING
// Just get B2n and convert to a Tangent number:
T t2n = fabs(b2n_asymptotic<T, Policy>(2 * n)) / (2 * n);
T p2 = ldexp(T(1), n);
if(tools::max_value<T>() / p2 < t2n)
return policies::raise_overflow_error<T>("boost::math::tangent_t2n<%1%>(std::size_t)", 0, T(n), Policy());
t2n *= p2;
p2 -= 1;
if(tools::max_value<T>() / p2 < t2n)
return policies::raise_overflow_error<T>("boost::math::tangent_t2n<%1%>(std::size_t)", 0, Policy());
t2n *= p2;
return t2n;
}
//
// We need to know the approximate value of /n/ which will
// cause bernoulli_b2n<T>(n) to return infinity - this allows
// us to elude a great deal of runtime checking for values below
// n, and only perform the full overflow checks when we know that we're
// getting close to the point where our calculations will overflow.
// We use Luschny's LogB3 formula (http://www.luschny.de/math/primes/bernincl.html)
// to find the limit, and since we're dealing with the log of the Bernoulli numbers
// we need only perform the calculation at double precision and not with T
// (which may be a multiprecision type). The limit returned is within 1 of the true
// limit for all the types tested. Note that although the code below is basically
// the same as b2n_asymptotic above, it has been recast as a continuous real-valued
// function as this makes the root finding go smoother/faster. It also omits the
// sign of the Bernoulli number.
//
struct max_bernoulli_root_functor
{
max_bernoulli_root_functor(long long t) : target(static_cast<double>(t)) {}
double operator()(double n)
{
BOOST_MATH_STD_USING
// Luschny LogB3(n) formula.
const double nx2(n * n);
const double approximate_log_of_bernoulli_bn
= ((boost::math::constants::half<double>() + n) * log(n))
+ ((boost::math::constants::half<double>() - n) * log(boost::math::constants::pi<double>()))
+ (((double(3) / 2) - n) * boost::math::constants::ln_two<double>())
+ ((n * (2 - (nx2 * 7) * (1 + ((nx2 * 30) * ((nx2 * 12) - 1))))) / (((nx2 * nx2) * nx2) * 2520));
return approximate_log_of_bernoulli_bn - target;
}
private:
double target;
};
template <class T, class Policy>
inline std::size_t find_bernoulli_overflow_limit(const mpl::false_&)
{
long long t = lltrunc(boost::math::tools::log_max_value<T>());
max_bernoulli_root_functor fun(t);
boost::math::tools::equal_floor tol;
boost::uintmax_t max_iter = boost::math::policies::get_max_root_iterations<Policy>();
return static_cast<std::size_t>(boost::math::tools::toms748_solve(fun, sqrt(double(t)), double(t), tol, max_iter).first) / 2;
}
template <class T, class Policy>
inline std::size_t find_bernoulli_overflow_limit(const mpl::true_&)
{
return max_bernoulli_index<bernoulli_imp_variant<T>::value>::value;
}
template <class T, class Policy>
std::size_t b2n_overflow_limit()
{
// This routine is called at program startup if it's called at all:
// that guarantees safe initialization of the static variable.
typedef mpl::bool_<(bernoulli_imp_variant<T>::value >= 1) && (bernoulli_imp_variant<T>::value <= 3)> tag_type;
static const std::size_t lim = find_bernoulli_overflow_limit<T, Policy>(tag_type());
return lim;
}
//
// The tangent numbers grow larger much more rapidly than the Bernoulli numbers do....
// so to compute the Bernoulli numbers from the tangent numbers, we need to avoid spurious
// overflow in the calculation, we can do this by scaling all the tangent number by some scale factor:
//
template <class T>
inline typename enable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2), T>::type tangent_scale_factor()
{
BOOST_MATH_STD_USING
return ldexp(T(1), std::numeric_limits<T>::min_exponent + 5);
}
template <class T>
inline typename disable_if_c<std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2), T>::type tangent_scale_factor()
{
return tools::min_value<T>() * 16;
}
//
// Initializer: ensure all our constants are initialized prior to the first call of main:
//
template <class T, class Policy>
struct bernoulli_initializer
{
struct init
{
init()
{
//
// We call twice, once to initialize our static table, and once to
// initialize our dymanic table:
//
boost::math::bernoulli_b2n<T>(2, Policy());
#ifndef BOOST_NO_EXCEPTIONS
try{
#endif
boost::math::bernoulli_b2n<T>(max_bernoulli_b2n<T>::value + 1, Policy());
#ifndef BOOST_NO_EXCEPTIONS
} catch(const std::overflow_error&){}
#endif
boost::math::tangent_t2n<T>(2, Policy());
}
void force_instantiate()const{}
};
static const init initializer;
static void force_instantiate()
{
initializer.force_instantiate();
}
};
template <class T, class Policy>
const typename bernoulli_initializer<T, Policy>::init bernoulli_initializer<T, Policy>::initializer;
//
// We need something to act as a cache for our calculated Bernoulli numbers. In order to
// ensure both fast access and thread safety, we need a stable table which may be extended
// in size, but which never reallocates: that way values already calculated may be accessed
// concurrently with another thread extending the table with new values.
//
// Very very simple vector class that will never allocate more than once, we could use
// boost::container::static_vector here, but that allocates on the stack, which may well
// cause issues for the amount of memory we want in the extreme case...
//
template <class T>
struct fixed_vector : private std::allocator<T>
{
typedef unsigned size_type;
typedef T* iterator;
typedef const T* const_iterator;
fixed_vector() : m_used(0)
{
std::size_t overflow_limit = 5 + b2n_overflow_limit<T, policies::policy<> >();
m_capacity = static_cast<unsigned>((std::min)(overflow_limit, static_cast<std::size_t>(100000u)));
m_data = this->allocate(m_capacity);
}
~fixed_vector()
{
for(unsigned i = 0; i < m_used; ++i)
this->destroy(&m_data[i]);
this->deallocate(m_data, m_capacity);
}
T& operator[](unsigned n) { BOOST_ASSERT(n < m_used); return m_data[n]; }
const T& operator[](unsigned n)const { BOOST_ASSERT(n < m_used); return m_data[n]; }
unsigned size()const { return m_used; }
unsigned size() { return m_used; }
void resize(unsigned n, const T& val)
{
if(n > m_capacity)
{
BOOST_THROW_EXCEPTION(std::runtime_error("Exhausted storage for Bernoulli numbers."));
}
for(unsigned i = m_used; i < n; ++i)
new (m_data + i) T(val);
m_used = n;
}
void resize(unsigned n) { resize(n, T()); }
T* begin() { return m_data; }
T* end() { return m_data + m_used; }
T* begin()const { return m_data; }
T* end()const { return m_data + m_used; }
unsigned capacity()const { return m_capacity; }
void clear() { m_used = 0; }
private:
T* m_data;
unsigned m_used, m_capacity;
};
template <class T, class Policy>
class bernoulli_numbers_cache
{
public:
bernoulli_numbers_cache() : m_overflow_limit((std::numeric_limits<std::size_t>::max)())
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_MATH_NO_ATOMIC_INT)
, m_counter(0)
#endif
, m_current_precision(boost::math::tools::digits<T>())
{}
typedef fixed_vector<T> container_type;
void tangent(std::size_t m)
{
static const std::size_t min_overflow_index = b2n_overflow_limit<T, Policy>() - 1;
tn.resize(static_cast<typename container_type::size_type>(m), T(0U));
BOOST_MATH_INSTRUMENT_VARIABLE(min_overflow_index);
std::size_t prev_size = m_intermediates.size();
m_intermediates.resize(m, T(0U));
if(prev_size == 0)
{
m_intermediates[1] = tangent_scale_factor<T>() /*T(1U)*/;
tn[0U] = T(0U);
tn[1U] = tangent_scale_factor<T>()/* T(1U)*/;
BOOST_MATH_INSTRUMENT_VARIABLE(tn[0]);
BOOST_MATH_INSTRUMENT_VARIABLE(tn[1]);
}
for(std::size_t i = std::max<size_t>(2, prev_size); i < m; i++)
{
bool overflow_check = false;
if(i >= min_overflow_index && (boost::math::tools::max_value<T>() / (i-1) < m_intermediates[1]) )
{
std::fill(tn.begin() + i, tn.end(), boost::math::tools::max_value<T>());
break;
}
m_intermediates[1] = m_intermediates[1] * (i-1);
for(std::size_t j = 2; j <= i; j++)
{
overflow_check =
(i >= min_overflow_index) && (
(boost::math::tools::max_value<T>() / (i - j) < m_intermediates[j])
|| (boost::math::tools::max_value<T>() / (i - j + 2) < m_intermediates[j-1])
|| (boost::math::tools::max_value<T>() - m_intermediates[j] * (i - j) < m_intermediates[j-1] * (i - j + 2))
|| ((boost::math::isinf)(m_intermediates[j]))
);
if(overflow_check)
{
std::fill(tn.begin() + i, tn.end(), boost::math::tools::max_value<T>());
break;
}
m_intermediates[j] = m_intermediates[j] * (i - j) + m_intermediates[j-1] * (i - j + 2);
}
if(overflow_check)
break; // already filled the tn...
tn[static_cast<typename container_type::size_type>(i)] = m_intermediates[i];
BOOST_MATH_INSTRUMENT_VARIABLE(i);
BOOST_MATH_INSTRUMENT_VARIABLE(tn[static_cast<typename container_type::size_type>(i)]);
}
}
void tangent_numbers_series(const std::size_t m)
{
BOOST_MATH_STD_USING
static const std::size_t min_overflow_index = b2n_overflow_limit<T, Policy>() - 1;
typename container_type::size_type old_size = bn.size();
tangent(m);
bn.resize(static_cast<typename container_type::size_type>(m));
if(!old_size)
{
bn[0] = 1;
old_size = 1;
}
T power_two(ldexp(T(1), static_cast<int>(2 * old_size)));
for(std::size_t i = old_size; i < m; i++)
{
T b(static_cast<T>(i * 2));
//
// Not only do we need to take care to avoid spurious over/under flow in
// the calculation, but we also need to avoid overflow altogether in case
// we're calculating with a type where "bad things" happen in that case:
//
b = b / (power_two * tangent_scale_factor<T>());
b /= (power_two - 1);
bool overflow_check = (i >= min_overflow_index) && (tools::max_value<T>() / tn[static_cast<typename container_type::size_type>(i)] < b);
if(overflow_check)
{
m_overflow_limit = i;
while(i < m)
{
b = std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : tools::max_value<T>();
bn[static_cast<typename container_type::size_type>(i)] = ((i % 2U) ? b : T(-b));
++i;
}
break;
}
else
{
b *= tn[static_cast<typename container_type::size_type>(i)];
}
power_two = ldexp(power_two, 2);
const bool b_neg = i % 2 == 0;
bn[static_cast<typename container_type::size_type>(i)] = ((!b_neg) ? b : T(-b));
}
}
template <class OutputIterator>
OutputIterator copy_bernoulli_numbers(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol)
{
//
// There are basically 3 thread safety options:
//
// 1) There are no threads (BOOST_HAS_THREADS is not defined).
// 2) There are threads, but we do not have a true atomic integer type,
// in this case we just use a mutex to guard against race conditions.
// 3) There are threads, and we have an atomic integer: in this case we can
// use the double-checked locking pattern to avoid thread synchronisation
// when accessing values already in the cache.
//
// First off handle the common case for overflow and/or asymptotic expansion:
//
if(start + n > bn.capacity())
{
if(start < bn.capacity())
{
out = copy_bernoulli_numbers(out, start, bn.capacity() - start, pol);
n -= bn.capacity() - start;
start = static_cast<std::size_t>(bn.capacity());
}
if(start < b2n_overflow_limit<T, Policy>() + 2u)
{
for(; n; ++start, --n)
{
*out = b2n_asymptotic<T, Policy>(static_cast<typename container_type::size_type>(start * 2U));
++out;
}
}
for(; n; ++start, --n)
{
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(start), pol);
++out;
}
return out;
}
#if !defined(BOOST_HAS_THREADS)
//
// Single threaded code, very simple:
//
if(m_current_precision < boost::math::tools::digits<T>())
{
bn.clear();
tn.clear();
m_intermediates.clear();
m_current_precision = boost::math::tools::digits<T>();
}
if(start + n >= bn.size())
{
std::size_t new_size = (std::min)((std::max)((std::max)(std::size_t(start + n), std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
tangent_numbers_series(new_size);
}
for(std::size_t i = (std::max)(std::size_t(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
{
*out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[i];
++out;
}
#elif defined(BOOST_MATH_NO_ATOMIC_INT)
//
// We need to grab a mutex every time we get here, for both readers and writers:
//
boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
if(m_current_precision < boost::math::tools::digits<T>())
{
bn.clear();
tn.clear();
m_intermediates.clear();
m_current_precision = boost::math::tools::digits<T>();
}
if(start + n >= bn.size())
{
std::size_t new_size = (std::min)((std::max)((std::max)(std::size_t(start + n), std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
tangent_numbers_series(new_size);
}
for(std::size_t i = (std::max)(std::size_t(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
{
*out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[i];
++out;
}
#else
//
// Double-checked locking pattern, lets us access cached already cached values
// without locking:
//
// Get the counter and see if we need to calculate more constants:
//
if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
|| (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()))
{
boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
|| (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()))
{
if(static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>())
{
bn.clear();
tn.clear();
m_intermediates.clear();
m_counter.store(0, BOOST_MATH_ATOMIC_NS::memory_order_release);
m_current_precision = boost::math::tools::digits<T>();
}
if(start + n >= bn.size())
{
std::size_t new_size = (std::min)((std::max)((std::max)(std::size_t(start + n), std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
tangent_numbers_series(new_size);
}
m_counter.store(static_cast<atomic_integer_type>(bn.size()), BOOST_MATH_ATOMIC_NS::memory_order_release);
}
}
for(std::size_t i = (std::max)(static_cast<std::size_t>(max_bernoulli_b2n<T>::value + 1), start); i < start + n; ++i)
{
*out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[static_cast<typename container_type::size_type>(i)];
++out;
}
#endif
return out;
}
template <class OutputIterator>
OutputIterator copy_tangent_numbers(OutputIterator out, std::size_t start, std::size_t n, const Policy& pol)
{
//
// There are basically 3 thread safety options:
//
// 1) There are no threads (BOOST_HAS_THREADS is not defined).
// 2) There are threads, but we do not have a true atomic integer type,
// in this case we just use a mutex to guard against race conditions.
// 3) There are threads, and we have an atomic integer: in this case we can
// use the double-checked locking pattern to avoid thread synchronisation
// when accessing values already in the cache.
//
//
// First off handle the common case for overflow and/or asymptotic expansion:
//
if(start + n > bn.capacity())
{
if(start < bn.capacity())
{
out = copy_tangent_numbers(out, start, bn.capacity() - start, pol);
n -= bn.capacity() - start;
start = static_cast<std::size_t>(bn.capacity());
}
if(start < b2n_overflow_limit<T, Policy>() + 2u)
{
for(; n; ++start, --n)
{
*out = t2n_asymptotic<T, Policy>(static_cast<typename container_type::size_type>(start));
++out;
}
}
for(; n; ++start, --n)
{
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(start), pol);
++out;
}
return out;
}
#if !defined(BOOST_HAS_THREADS)
//
// Single threaded code, very simple:
//
if(m_current_precision < boost::math::tools::digits<T>())
{
bn.clear();
tn.clear();
m_intermediates.clear();
m_current_precision = boost::math::tools::digits<T>();
}
if(start + n >= bn.size())
{
std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
tangent_numbers_series(new_size);
}
for(std::size_t i = start; i < start + n; ++i)
{
if(i >= m_overflow_limit)
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
else
{
if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)])
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
else
*out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>();
}
++out;
}
#elif defined(BOOST_MATH_NO_ATOMIC_INT)
//
// We need to grab a mutex every time we get here, for both readers and writers:
//
boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
if(m_current_precision < boost::math::tools::digits<T>())
{
bn.clear();
tn.clear();
m_intermediates.clear();
m_current_precision = boost::math::tools::digits<T>();
}
if(start + n >= bn.size())
{
std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
tangent_numbers_series(new_size);
}
for(std::size_t i = start; i < start + n; ++i)
{
if(i >= m_overflow_limit)
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
else
{
if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)])
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
else
*out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>();
}
++out;
}
#else
//
// Double-checked locking pattern, lets us access cached already cached values
// without locking:
//
// Get the counter and see if we need to calculate more constants:
//
if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
|| (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()))
{
boost::detail::lightweight_mutex::scoped_lock l(m_mutex);
if((static_cast<std::size_t>(m_counter.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < start + n)
|| (static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>()))
{
if(static_cast<int>(m_current_precision.load(BOOST_MATH_ATOMIC_NS::memory_order_consume)) < boost::math::tools::digits<T>())
{
bn.clear();
tn.clear();
m_intermediates.clear();
m_counter.store(0, BOOST_MATH_ATOMIC_NS::memory_order_release);
m_current_precision = boost::math::tools::digits<T>();
}
if(start + n >= bn.size())
{
std::size_t new_size = (std::min)((std::max)((std::max)(start + n, std::size_t(bn.size() + 20)), std::size_t(50)), std::size_t(bn.capacity()));
tangent_numbers_series(new_size);
}
m_counter.store(static_cast<atomic_integer_type>(bn.size()), BOOST_MATH_ATOMIC_NS::memory_order_release);
}
}
for(std::size_t i = start; i < start + n; ++i)
{
if(i >= m_overflow_limit)
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
else
{
if(tools::max_value<T>() * tangent_scale_factor<T>() < tn[static_cast<typename container_type::size_type>(i)])
*out = policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol);
else
*out = tn[static_cast<typename container_type::size_type>(i)] / tangent_scale_factor<T>();
}
++out;
}
#endif
return out;
}
private:
//
// The caches for Bernoulli and tangent numbers, once allocated,
// these must NEVER EVER reallocate as it breaks our thread
// safety guarantees:
//
fixed_vector<T> bn, tn;
std::vector<T> m_intermediates;
// The value at which we know overflow has already occurred for the Bn:
std::size_t m_overflow_limit;
#if !defined(BOOST_HAS_THREADS)
int m_current_precision;
#elif defined(BOOST_MATH_NO_ATOMIC_INT)
boost::detail::lightweight_mutex m_mutex;
int m_current_precision;
#else
boost::detail::lightweight_mutex m_mutex;
atomic_counter_type m_counter, m_current_precision;
#endif
};
template <class T, class Policy>
inline bernoulli_numbers_cache<T, Policy>& get_bernoulli_numbers_cache()
{
//
// Force this function to be called at program startup so all the static variables
// get initailzed then (thread safety).
//
bernoulli_initializer<T, Policy>::force_instantiate();
static bernoulli_numbers_cache<T, Policy> data;
return data;
}
}}}
#endif // BOOST_MATH_BERNOULLI_DETAIL_HPP

View File

@@ -0,0 +1,87 @@
// Copyright (c) 2013 Anton Bikineev
// 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 is a partial header, do not include on it's own!!!
//
// Linear combination for bessel derivatives are defined here
#ifndef BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP
#define BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP
#ifdef _MSC_VER
#pragma once
#endif
namespace boost{ namespace math{ namespace detail{
template <class T, class Tag, class Policy>
inline T bessel_j_derivative_linear(T v, T x, Tag tag, Policy pol)
{
return (boost::math::detail::cyl_bessel_j_imp<T>(v-1, x, tag, pol) - boost::math::detail::cyl_bessel_j_imp<T>(v+1, x, tag, pol)) / 2;
}
template <class T, class Policy>
inline T bessel_j_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol)
{
return (boost::math::detail::cyl_bessel_j_imp<T>(itrunc(v-1), x, tag, pol) - boost::math::detail::cyl_bessel_j_imp<T>(itrunc(v+1), x, tag, pol)) / 2;
}
template <class T, class Policy>
inline T sph_bessel_j_derivative_linear(unsigned v, T x, Policy pol)
{
return (v / x) * boost::math::detail::sph_bessel_j_imp<T>(v, x, pol) - boost::math::detail::sph_bessel_j_imp<T>(v+1, x, pol);
}
template <class T, class Policy>
inline T bessel_i_derivative_linear(T v, T x, Policy pol)
{
T result = boost::math::detail::cyl_bessel_i_imp<T>(v - 1, x, pol);
if(result >= tools::max_value<T>())
return result; // result is infinite
T result2 = boost::math::detail::cyl_bessel_i_imp<T>(v + 1, x, pol);
if(result2 >= tools::max_value<T>() - result)
return result2; // result is infinite
return (result + result2) / 2;
}
template <class T, class Tag, class Policy>
inline T bessel_k_derivative_linear(T v, T x, Tag tag, Policy pol)
{
T result = boost::math::detail::cyl_bessel_k_imp<T>(v - 1, x, tag, pol);
if(result >= tools::max_value<T>())
return -result; // result is infinite
T result2 = boost::math::detail::cyl_bessel_k_imp<T>(v + 1, x, tag, pol);
if(result2 >= tools::max_value<T>() - result)
return -result2; // result is infinite
return (result + result2) / -2;
}
template <class T, class Policy>
inline T bessel_k_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol)
{
return (boost::math::detail::cyl_bessel_k_imp<T>(itrunc(v-1), x, tag, pol) + boost::math::detail::cyl_bessel_k_imp<T>(itrunc(v+1), x, tag, pol)) / -2;
}
template <class T, class Tag, class Policy>
inline T bessel_y_derivative_linear(T v, T x, Tag tag, Policy pol)
{
return (boost::math::detail::cyl_neumann_imp<T>(v-1, x, tag, pol) - boost::math::detail::cyl_neumann_imp<T>(v+1, x, tag, pol)) / 2;
}
template <class T, class Policy>
inline T bessel_y_derivative_linear(T v, T x, const bessel_int_tag& tag, Policy pol)
{
return (boost::math::detail::cyl_neumann_imp<T>(itrunc(v-1), x, tag, pol) - boost::math::detail::cyl_neumann_imp<T>(itrunc(v+1), x, tag, pol)) / 2;
}
template <class T, class Policy>
inline T sph_neumann_derivative_linear(unsigned v, T x, Policy pol)
{
return (v / x) * boost::math::detail::sph_neumann_imp<T>(v, x, pol) - boost::math::detail::sph_neumann_imp<T>(v+1, x, pol);
}
}}} // namespaces
#endif // BOOST_MATH_SF_DETAIL_BESSEL_DERIVATIVES_LINEAR_HPP

View File

@@ -0,0 +1,554 @@
// Copyright (c) 2006 Xiaogang Zhang
// Copyright (c) 2017 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_BESSEL_I0_HPP
#define BOOST_MATH_BESSEL_I0_HPP
#ifdef _MSC_VER
#pragma once
#endif
#include <boost/math/tools/rational.hpp>
#include <boost/math/tools/big_constant.hpp>
#include <boost/assert.hpp>
// Modified Bessel function of the first kind of order zero
// we use the approximating forms derived in:
// "Rational Approximations for the Modified Bessel Function of the First Kind I0(x) for Computations with Double Precision"
// by Pavel Holoborodko,
// see http://www.advanpix.com/2015/11/11/rational-approximations-for-the-modified-bessel-function-of-the-first-kind-i0-computations-double-precision
// The actual coefficients used are our own, and extend Pavel's work to precision's other than double.
namespace boost { namespace math { namespace detail{
template <typename T>
T bessel_i0(const T& x);
template <class T, class tag>
struct bessel_i0_initializer
{
struct init
{
init()
{
do_init(tag());
}
static void do_init(const mpl::int_<64>&)
{
bessel_i0(T(1));
bessel_i0(T(8));
bessel_i0(T(12));
bessel_i0(T(40));
bessel_i0(T(101));
}
static void do_init(const mpl::int_<113>&)
{
bessel_i0(T(1));
bessel_i0(T(10));
bessel_i0(T(20));
bessel_i0(T(40));
bessel_i0(T(101));
}
template <class U>
static void do_init(const U&) {}
void force_instantiate()const {}
};
static const init initializer;
static void force_instantiate()
{
initializer.force_instantiate();
}
};
template <class T, class tag>
const typename bessel_i0_initializer<T, tag>::init bessel_i0_initializer<T, tag>::initializer;
template <typename T, int N>
T bessel_i0_imp(const T&, const mpl::int_<N>&)
{
BOOST_ASSERT(0);
return 0;
}
template <typename T>
T bessel_i0_imp(const T& x, const mpl::int_<24>&)
{
BOOST_MATH_STD_USING
if(x < 7.75)
{
// Max error in interpolated form: 3.929e-08
// Max Error found at float precision = Poly: 1.991226e-07
static const float P[] = {
1.00000003928615375e+00f,
2.49999576572179639e-01f,
2.77785268558399407e-02f,
1.73560257755821695e-03f,
6.96166518788906424e-05f,
1.89645733877137904e-06f,
4.29455004657565361e-08f,
3.90565476357034480e-10f,
1.48095934745267240e-11f
};
T a = x * x / 4;
return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
}
else if(x < 50)
{
// Max error in interpolated form: 5.195e-08
// Max Error found at float precision = Poly: 8.502534e-08
static const float P[] = {
3.98942651588301770e-01f,
4.98327234176892844e-02f,
2.91866904423115499e-02f,
1.35614940793742178e-02f,
1.31409251787866793e-01f
};
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
}
else
{
// Max error in interpolated form: 1.782e-09
// Max Error found at float precision = Poly: 6.473568e-08
static const float P[] = {
3.98942391532752700e-01f,
4.98455950638200020e-02f,
2.94835666900682535e-02f
};
T ex = exp(x / 2);
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
result *= ex;
return result;
}
}
template <typename T>
T bessel_i0_imp(const T& x, const mpl::int_<53>&)
{
BOOST_MATH_STD_USING
if(x < 7.75)
{
// Bessel I0 over[10 ^ -16, 7.75]
// Max error in interpolated form : 3.042e-18
// Max Error found at double precision = Poly : 5.106609e-16 Cheb : 5.239199e-16
static const double P[] = {
1.00000000000000000e+00,
2.49999999999999909e-01,
2.77777777777782257e-02,
1.73611111111023792e-03,
6.94444444453352521e-05,
1.92901234513219920e-06,
3.93675991102510739e-08,
6.15118672704439289e-10,
7.59407002058973446e-12,
7.59389793369836367e-14,
6.27767773636292611e-16,
4.34709704153272287e-18,
2.63417742690109154e-20,
1.13943037744822825e-22,
9.07926920085624812e-25
};
T a = x * x / 4;
return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
}
else if(x < 500)
{
// Max error in interpolated form : 1.685e-16
// Max Error found at double precision = Poly : 2.575063e-16 Cheb : 2.247615e+00
static const double P[] = {
3.98942280401425088e-01,
4.98677850604961985e-02,
2.80506233928312623e-02,
2.92211225166047873e-02,
4.44207299493659561e-02,
1.30970574605856719e-01,
-3.35052280231727022e+00,
2.33025711583514727e+02,
-1.13366350697172355e+04,
4.24057674317867331e+05,
-1.23157028595698731e+07,
2.80231938155267516e+08,
-5.01883999713777929e+09,
7.08029243015109113e+10,
-7.84261082124811106e+11,
6.76825737854096565e+12,
-4.49034849696138065e+13,
2.24155239966958995e+14,
-8.13426467865659318e+14,
2.02391097391687777e+15,
-3.08675715295370878e+15,
2.17587543863819074e+15
};
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
}
else
{
// Max error in interpolated form : 2.437e-18
// Max Error found at double precision = Poly : 1.216719e-16
static const double P[] = {
3.98942280401432905e-01,
4.98677850491434560e-02,
2.80506308916506102e-02,
2.92179096853915176e-02,
4.53371208762579442e-02
};
T ex = exp(x / 2);
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
result *= ex;
return result;
}
}
template <typename T>
T bessel_i0_imp(const T& x, const mpl::int_<64>&)
{
BOOST_MATH_STD_USING
if(x < 7.75)
{
// Bessel I0 over[10 ^ -16, 7.75]
// Max error in interpolated form : 3.899e-20
// Max Error found at float80 precision = Poly : 1.770840e-19
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 64, 9.99999999999999999961011629e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.50000000000000001321873912e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.77777777777777703400424216e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.73611111111112764793802701e-03),
BOOST_MATH_BIG_CONSTANT(T, 64, 6.94444444444251461247253525e-05),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.92901234569262206386118739e-06),
BOOST_MATH_BIG_CONSTANT(T, 64, 3.93675988851131457141005209e-08),
BOOST_MATH_BIG_CONSTANT(T, 64, 6.15118734688297476454205352e-10),
BOOST_MATH_BIG_CONSTANT(T, 64, 7.59405797058091016449222685e-12),
BOOST_MATH_BIG_CONSTANT(T, 64, 7.59406599631719800679835140e-14),
BOOST_MATH_BIG_CONSTANT(T, 64, 6.27598961062070013516660425e-16),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.35920318970387940278362992e-18),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.57372492687715452949437981e-20),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.33908663475949906992942204e-22),
BOOST_MATH_BIG_CONSTANT(T, 64, 5.15976668870980234582896010e-25),
BOOST_MATH_BIG_CONSTANT(T, 64, 3.46240478946376069211156548e-27)
};
T a = x * x / 4;
return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
}
else if(x < 10)
{
// Maximum Deviation Found: 6.906e-21
// Expected Error Term : -6.903e-21
// Maximum Relative Change in Control Points : 1.631e-04
// Max Error found at float80 precision = Poly : 7.811948e-21
static const T Y = 4.051098823547363281250e-01f;
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 64, -6.158081780620616479492e-03),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.883635969834048766148e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 7.892782002476195771920e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.478784996478070170327e+00),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.988611837308006851257e+01),
BOOST_MATH_BIG_CONSTANT(T, 64, -4.140133766747436806179e+02),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.117316447921276453271e+03),
BOOST_MATH_BIG_CONSTANT(T, 64, -2.942353667455141676001e+04),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.493482682461387081534e+05),
BOOST_MATH_BIG_CONSTANT(T, 64, -5.228100538921466124653e+05),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.195279248600467989454e+06),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.601530760654337045917e+06),
BOOST_MATH_BIG_CONSTANT(T, 64, 9.504921137873298402679e+05)
};
return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x);
}
else if(x < 15)
{
// Maximum Deviation Found: 4.083e-21
// Expected Error Term : -4.025e-21
// Maximum Relative Change in Control Points : 1.304e-03
// Max Error found at float80 precision = Poly : 2.303527e-20
static const T Y = 4.033188819885253906250e-01f;
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 64, -4.376373876116109401062e-03),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.982899138682911273321e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 3.109477529533515397644e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.163760580110576407673e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.776501832837367371883e+00),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.101478069227776656318e+02),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.892071912448960299773e+03),
BOOST_MATH_BIG_CONSTANT(T, 64, -2.417739279982328117483e+04),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.296963447724067390552e+05),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.598589306710589358747e+06),
BOOST_MATH_BIG_CONSTANT(T, 64, 7.903662411851774878322e+06),
BOOST_MATH_BIG_CONSTANT(T, 64, -2.622677059040339516093e+07),
BOOST_MATH_BIG_CONSTANT(T, 64, 5.227776578828667629347e+07),
BOOST_MATH_BIG_CONSTANT(T, 64, -4.727797957441040896878e+07)
};
return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x);
}
else if(x < 50)
{
// Max error in interpolated form: 1.035e-21
// Max Error found at float80 precision = Poly: 1.885872e-21
static const T Y = 4.011702537536621093750e-01f;
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 64, -2.227973351806078464328e-03),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.986778486088017419036e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.805066823812285310011e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.921443721160964964623e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.517504941996594744052e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 6.316922639868793684401e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.535891099168810015433e+00),
BOOST_MATH_BIG_CONSTANT(T, 64, -4.706078229522448308087e+01),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.351015763079160914632e+03),
BOOST_MATH_BIG_CONSTANT(T, 64, -2.948809013999277355098e+04),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.967598958582595361757e+05),
BOOST_MATH_BIG_CONSTANT(T, 64, -6.346924657995383019558e+06),
BOOST_MATH_BIG_CONSTANT(T, 64, 5.998794574259956613472e+07),
BOOST_MATH_BIG_CONSTANT(T, 64, -4.016371355801690142095e+08),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.768791455631826490838e+09),
BOOST_MATH_BIG_CONSTANT(T, 64, -4.441995678177349895640e+09),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.482292669974971387738e+09)
};
return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x);
}
else
{
// Bessel I0 over[50, INF]
// Max error in interpolated form : 5.587e-20
// Max Error found at float80 precision = Poly : 8.776852e-20
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401432677955074061e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.98677850501789875615574058e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.80506290908675604202206833e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.92194052159035901631494784e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.47422430732256364094681137e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 9.05971614435738691235525172e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.29180522595459823234266708e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, 6.15122547776140254569073131e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, 7.48491812136365376477357324e+00),
BOOST_MATH_BIG_CONSTANT(T, 64, -2.45569740166506688169730713e+02),
BOOST_MATH_BIG_CONSTANT(T, 64, 9.66857566379480730407063170e+03),
BOOST_MATH_BIG_CONSTANT(T, 64, -2.71924083955641197750323901e+05),
BOOST_MATH_BIG_CONSTANT(T, 64, 5.74276685704579268845870586e+06),
BOOST_MATH_BIG_CONSTANT(T, 64, -8.89753803265734681907148778e+07),
BOOST_MATH_BIG_CONSTANT(T, 64, 9.82590905134996782086242180e+08),
BOOST_MATH_BIG_CONSTANT(T, 64, -7.30623197145529889358596301e+09),
BOOST_MATH_BIG_CONSTANT(T, 64, 3.27310000726207055200805893e+10),
BOOST_MATH_BIG_CONSTANT(T, 64, -6.64365417189215599168817064e+10)
};
T ex = exp(x / 2);
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
result *= ex;
return result;
}
}
template <typename T>
T bessel_i0_imp(const T& x, const mpl::int_<113>&)
{
BOOST_MATH_STD_USING
if(x < 7.75)
{
// Bessel I0 over[10 ^ -34, 7.75]
// Max error in interpolated form : 1.274e-34
// Max Error found at float128 precision = Poly : 3.096091e-34
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0000000000000000000000000000000001273856e+00),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.4999999999999999999999999999999107477496e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.7777777777777777777777777777881795230918e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.7361111111111111111111111106290091648808e-03),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444444444444445629960334523101e-05),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.9290123456790123456790105563456483249753e-06),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.9367598891408415217940836339080514004844e-08),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.1511873267825648777900014857992724731476e-10),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266233066162999610732449709209e-12),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266232783124723601470051895304e-14),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.2760813455591936763439337059117957836078e-16),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.3583898233049738471136482147779094353096e-18),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.5789288895299965395422423848480340736308e-20),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.3157800456718804437960453545507623434606e-22),
BOOST_MATH_BIG_CONSTANT(T, 113, 5.8479113149412360748032684260932041506493e-25),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.2843403488398038539283241944594140493394e-27),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.9042925594356556196790242908697582021825e-30),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.4395919891312152120710245152115597111101e-32),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.7580986145276689333214547502373003196707e-35),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.6886514018062348877723837017198859723889e-37),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.8540558465757554512570197585002702777999e-40),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.4684706070226893763741850944911705726436e-43),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.0210715309399646335858150349406935414314e-45)
};
T a = x * x / 4;
return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
}
else if(x < 15)
{
// Bessel I0 over[7.75, 15]
// Max error in interpolated form : 7.534e-35
// Max Error found at float128 precision = Poly : 6.123912e-34
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 113, 9.9999999999999999992388573069504617493518e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.5000000000000000007304739268173096975340e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.7777777777777777744261405400543564492074e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.7361111111111111209006987259719750726867e-03),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444442399703186871329381908321e-05),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.9290123456790126709286741580242189785431e-06),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.9367598891408374246503061422528266924389e-08),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.1511873267826068395343047827801353170966e-10),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281262673459688011737168286944521e-12),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281291583769928563167645746144508e-14),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.2760813455438840231126529638737436950274e-16),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.3583898233839583885132809584770578894948e-18),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.5789288891798658971960571838369339742994e-20),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.3157800470129311623308216856009970266088e-22),
BOOST_MATH_BIG_CONSTANT(T, 113, 5.8479112701534604520063520412207286692581e-25),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.2843404822552330714586265081801727491890e-27),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.9042888166225242675881424439818162458179e-30),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.4396027771820721384198604723320045236973e-32),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.7577659910606076328136207973456511895030e-35),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.6896548123724136624716224328803899914646e-37),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.8285850162160539150210466453921758781984e-40),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.9419071894227736216423562425429524883562e-43),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.4720374049498608905571855665134539425038e-45),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.7763533278527958112907118930154738930378e-48),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.1213839473168678646697528580511702663617e-51),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0648035313124146852372607519737686740964e-53),
-BOOST_MATH_BIG_CONSTANT(T, 113, 5.1255595184052024349371058585102280860878e-57),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.4652470895944157957727948355523715335882e-59)
};
T a = x * x / 4;
return a * boost::math::tools::evaluate_polynomial(P, a) + 1;
}
else if(x < 30)
{
// Max error in interpolated form : 1.808e-34
// Max Error found at float128 precision = Poly : 2.399403e-34
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040870793650581242239624530714032e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867780576714783790784348982178607842250e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.8051948347934462928487999569249907599510e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.8971143420388958551176254291160976367263e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.8197359701715582763961322341827341098897e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -3.3430484862908317377522273217643346601271e+00),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.7884507603213662610604413960838990199224e+02),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.8304926482356755790062999202373909300514e+04),
BOOST_MATH_BIG_CONSTANT(T, 113, 9.8867173178574875515293357145875120137676e+05),
BOOST_MATH_BIG_CONSTANT(T, 113, -4.4261178812193528551544261731796888257644e+07),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.6453010340778116475788083817762403540097e+09),
BOOST_MATH_BIG_CONSTANT(T, 113, -5.0432401330113978669454035365747869477960e+10),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.2462165331309799059332310595587606836357e+12),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.3299800389951335932792950236410844978273e+13),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.5748218240248714177527965706790413406639e+14),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.8330014378766930869945511450377736037385e+15),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.8494610073827453236940544799030787866218e+17),
BOOST_MATH_BIG_CONSTANT(T, 113, 5.7244661371420647691301043350229977856476e+18),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.2386378807889388140099109087465781254321e+20),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.1104000573102013529518477353943384110982e+21),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.9426541092239879262282594572224300191016e+22),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.4061439136301913488512592402635688101020e+23),
BOOST_MATH_BIG_CONSTANT(T, 113, -3.2836554760521986358980180942859101564671e+24),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.6270285589905206294944214795661236766988e+25),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.7278631455211972017740134341610659484259e+26),
BOOST_MATH_BIG_CONSTANT(T, 113, 9.1971734473772196124736986948034978906801e+26),
BOOST_MATH_BIG_CONSTANT(T, 113, -3.8669270707172568763908838463689093500098e+27),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.2368879358870281916900125550129211146626e+28),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.8296235063297831758204519071113999839858e+28),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.1253861666023020670144616019148954773662e+28),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.8809536950051955163648980306847791014734e+28) };
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
}
else if(x < 100)
{
// Bessel I0 over[30, 100]
// Max error in interpolated form : 1.487e-34
// Max Error found at float128 precision = Poly : 1.929924e-34
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793996798658172135362278e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867785050179084714910130342157246539820e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.8050629090725751585266360464766768437048e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.9219405302833158254515212437025679637597e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.4742214371598631578107310396249912330627e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 9.0602983776478659136184969363625092585520e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.2839507231977478205885469900971893734770e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.8925739165733823730525449511456529001868e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.4238082222874015159424842335385854632223e+00),
BOOST_MATH_BIG_CONSTANT(T, 113, 9.6759648427182491050716309699208988458050e+00),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.7292246491169360014875196108746167872215e+01),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.1001411442786230340015781205680362993575e+01),
BOOST_MATH_BIG_CONSTANT(T, 113, 9.8277628835804873490331739499978938078848e+03),
BOOST_MATH_BIG_CONSTANT(T, 113, -3.1208326312801432038715638596517882759639e+05),
BOOST_MATH_BIG_CONSTANT(T, 113, 9.4813611580683862051838126076298945680803e+06),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.1278197693321821164135890132925119054391e+08),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.3190303792682886967459489059860595063574e+09),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.1580767338646580750893606158043485767644e+10),
BOOST_MATH_BIG_CONSTANT(T, 113, -5.0256008808415702780816006134784995506549e+11),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.9044186472918017896554580836514681614475e+13),
BOOST_MATH_BIG_CONSTANT(T, 113, -3.2521078890073151875661384381880225635135e+14),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.3620352486836976842181057590770636605454e+15),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.0375525734060401555856465179734887312420e+16),
BOOST_MATH_BIG_CONSTANT(T, 113, 5.6392664899881014534361728644608549445131e+16)
};
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
}
else
{
// Bessel I0 over[100, INF]
// Max error in interpolated form : 5.459e-35
// Max Error found at float128 precision = Poly : 1.472240e-34
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793994605993438166526772e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867785050179084742493257495245185241487e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.8050629090725735167652437695397756897920e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.9219405302839307466358297347675795965363e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.4742214369972689474366968442268908028204e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 9.0602984099194778006610058410222616383078e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.2839502241666629677015839125593079416327e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.8926354981801627920292655818232972385750e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.4231921590621824187100989532173995000655e+00),
BOOST_MATH_BIG_CONSTANT(T, 113, 9.7264260959693775207585700654645245723497e+00),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.3890136225398811195878046856373030127018e+01),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.1999720924619285464910452647408431234369e+02),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.2076909538525038580501368530598517194748e+03),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.5684635141332367730007149159063086133399e+03),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.5178192543258299267923025833141286569141e+04),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.2966297919851965784482163987240461837728e+05) };
T ex = exp(x / 2);
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
result *= ex;
return result;
}
}
template <typename T>
T bessel_i0_imp(const T& x, const mpl::int_<0>&)
{
if(boost::math::tools::digits<T>() <= 24)
return bessel_i0_imp(x, mpl::int_<24>());
else if(boost::math::tools::digits<T>() <= 53)
return bessel_i0_imp(x, mpl::int_<53>());
else if(boost::math::tools::digits<T>() <= 64)
return bessel_i0_imp(x, mpl::int_<64>());
else if(boost::math::tools::digits<T>() <= 113)
return bessel_i0_imp(x, mpl::int_<113>());
BOOST_ASSERT(0);
return 0;
}
template <typename T>
inline T bessel_i0(const T& x)
{
typedef mpl::int_<
std::numeric_limits<T>::digits == 0 ?
0 :
std::numeric_limits<T>::digits <= 24 ?
24 :
std::numeric_limits<T>::digits <= 53 ?
53 :
std::numeric_limits<T>::digits <= 64 ?
64 :
std::numeric_limits<T>::digits <= 113 ?
113 : -1
> tag_type;
bessel_i0_initializer<T, tag_type>::force_instantiate();
return bessel_i0_imp(x, tag_type());
}
}}} // namespaces
#endif // BOOST_MATH_BESSEL_I0_HPP

View File

@@ -0,0 +1,577 @@
// Modified Bessel function of the first kind of order zero
// we use the approximating forms derived in:
// "Rational Approximations for the Modified Bessel Function of the First Kind I1(x) for Computations with Double Precision"
// by Pavel Holoborodko,
// see http://www.advanpix.com/2015/11/12/rational-approximations-for-the-modified-bessel-function-of-the-first-kind-i1-for-computations-with-double-precision/
// The actual coefficients used are our own, and extend Pavel's work to precision's other than double.
#ifndef BOOST_MATH_BESSEL_I1_HPP
#define BOOST_MATH_BESSEL_I1_HPP
#ifdef _MSC_VER
#pragma once
#endif
#include <boost/math/tools/rational.hpp>
#include <boost/math/tools/big_constant.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(const T& x);
template <class T, class tag>
struct bessel_i1_initializer
{
struct init
{
init()
{
do_init(tag());
}
static void do_init(const mpl::int_<64>&)
{
bessel_i1(T(1));
bessel_i1(T(15));
bessel_i1(T(80));
bessel_i1(T(101));
}
static void do_init(const mpl::int_<113>&)
{
bessel_i1(T(1));
bessel_i1(T(10));
bessel_i1(T(14));
bessel_i1(T(19));
bessel_i1(T(34));
bessel_i1(T(99));
bessel_i1(T(101));
}
template <class U>
static void do_init(const U&) {}
void force_instantiate()const{}
};
static const init initializer;
static void force_instantiate()
{
initializer.force_instantiate();
}
};
template <class T, class tag>
const typename bessel_i1_initializer<T, tag>::init bessel_i1_initializer<T, tag>::initializer;
template <typename T, int N>
T bessel_i1_imp(const T&, const mpl::int_<N>&)
{
BOOST_ASSERT(0);
return 0;
}
template <typename T>
T bessel_i1_imp(const T& x, const mpl::int_<24>&)
{
BOOST_MATH_STD_USING
if(x < 7.75)
{
//Max error in interpolated form : 1.348e-08
// Max Error found at float precision = Poly : 1.469121e-07
static const float P[] = {
8.333333221e-02f,
6.944453712e-03f,
3.472097211e-04f,
1.158047174e-05f,
2.739745142e-07f,
5.135884609e-09f,
5.262251502e-11f,
1.331933703e-12f
};
T a = x * x / 4;
T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
}
else
{
// Max error in interpolated form: 9.000e-08
// Max Error found at float precision = Poly: 1.044345e-07
static const float P[] = {
3.98942115977513013e-01f,
-1.49581264836620262e-01f,
-4.76475741878486795e-02f,
-2.65157315524784407e-02f,
-1.47148600683672014e-01f
};
T ex = exp(x / 2);
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
result *= ex;
return result;
}
}
template <typename T>
T bessel_i1_imp(const T& x, const mpl::int_<53>&)
{
BOOST_MATH_STD_USING
if(x < 7.75)
{
// Bessel I0 over[10 ^ -16, 7.75]
// Max error in interpolated form: 5.639e-17
// Max Error found at double precision = Poly: 1.795559e-16
static const double P[] = {
8.333333333333333803e-02,
6.944444444444341983e-03,
3.472222222225921045e-04,
1.157407407354987232e-05,
2.755731926254790268e-07,
4.920949692800671435e-09,
6.834657311305621830e-11,
7.593969849687574339e-13,
6.904822652741917551e-15,
5.220157095351373194e-17,
3.410720494727771276e-19,
1.625212890947171108e-21,
1.332898928162290861e-23
};
T a = x * x / 4;
T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
}
else if(x < 500)
{
// Max error in interpolated form: 1.796e-16
// Max Error found at double precision = Poly: 2.898731e-16
static const double P[] = {
3.989422804014406054e-01,
-1.496033551613111533e-01,
-4.675104253598537322e-02,
-4.090895951581637791e-02,
-5.719036414430205390e-02,
-1.528189554374492735e-01,
3.458284470977172076e+00,
-2.426181371595021021e+02,
1.178785865993440669e+04,
-4.404655582443487334e+05,
1.277677779341446497e+07,
-2.903390398236656519e+08,
5.192386898222206474e+09,
-7.313784438967834057e+10,
8.087824484994859552e+11,
-6.967602516005787001e+12,
4.614040809616582764e+13,
-2.298849639457172489e+14,
8.325554073334618015e+14,
-2.067285045778906105e+15,
3.146401654361325073e+15,
-2.213318202179221945e+15
};
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
}
else
{
// Max error in interpolated form: 1.320e-19
// Max Error found at double precision = Poly: 7.065357e-17
static const double P[] = {
3.989422804014314820e-01,
-1.496033551467584157e-01,
-4.675105322571775911e-02,
-4.090421597376992892e-02,
-5.843630344778927582e-02
};
T ex = exp(x / 2);
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
result *= ex;
return result;
}
}
template <typename T>
T bessel_i1_imp(const T& x, const mpl::int_<64>&)
{
BOOST_MATH_STD_USING
if(x < 7.75)
{
// Bessel I0 over[10 ^ -16, 7.75]
// Max error in interpolated form: 8.086e-21
// Max Error found at float80 precision = Poly: 7.225090e-20
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 64, 8.33333333333333333340071817e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 6.94444444444444442462728070e-03),
BOOST_MATH_BIG_CONSTANT(T, 64, 3.47222222222222318886683883e-04),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.15740740740738880709555060e-05),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.75573192240046222242685145e-07),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.92094986131253986838697503e-09),
BOOST_MATH_BIG_CONSTANT(T, 64, 6.83465258979924922633502182e-11),
BOOST_MATH_BIG_CONSTANT(T, 64, 7.59405830675154933645967137e-13),
BOOST_MATH_BIG_CONSTANT(T, 64, 6.90369179710633344508897178e-15),
BOOST_MATH_BIG_CONSTANT(T, 64, 5.23003610041709452814262671e-17),
BOOST_MATH_BIG_CONSTANT(T, 64, 3.35291901027762552549170038e-19),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.83991379419781823063672109e-21),
BOOST_MATH_BIG_CONSTANT(T, 64, 8.87732714140192556332037815e-24),
BOOST_MATH_BIG_CONSTANT(T, 64, 3.32120654663773147206454247e-26),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.95294659305369207813486871e-28)
};
T a = x * x / 4;
T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
}
else if(x < 20)
{
// Max error in interpolated form: 4.258e-20
// Max Error found at float80 precision = Poly: 2.851105e-19
// Maximum Deviation Found : 3.887e-20
// Expected Error Term : 3.887e-20
// Maximum Relative Change in Control Points : 1.681e-04
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942260530218897338680e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.49599542849073670179540e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, -4.70492865454119188276875e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, -3.12389893307392002405869e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.49696126385202602071197e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, -3.84206507612717711565967e+01),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.14748094784412558689584e+03),
BOOST_MATH_BIG_CONSTANT(T, 64, -7.70652726663596993005669e+04),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.01659736164815617174439e+06),
BOOST_MATH_BIG_CONSTANT(T, 64, -4.04740659606466305607544e+07),
BOOST_MATH_BIG_CONSTANT(T, 64, 6.38383394696382837263656e+08),
BOOST_MATH_BIG_CONSTANT(T, 64, -8.00779638649147623107378e+09),
BOOST_MATH_BIG_CONSTANT(T, 64, 8.02338237858684714480491e+10),
BOOST_MATH_BIG_CONSTANT(T, 64, -6.41198553664947312995879e+11),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.05915186909564986897554e+12),
BOOST_MATH_BIG_CONSTANT(T, 64, -2.00907636964168581116181e+13),
BOOST_MATH_BIG_CONSTANT(T, 64, 7.60855263982359981275199e+13),
BOOST_MATH_BIG_CONSTANT(T, 64, -2.12901817219239205393806e+14),
BOOST_MATH_BIG_CONSTANT(T, 64, 4.14861794397709807823575e+14),
BOOST_MATH_BIG_CONSTANT(T, 64, -5.02808138522587680348583e+14),
BOOST_MATH_BIG_CONSTANT(T, 64, 2.85505477056514919387171e+14)
};
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
}
else if(x < 100)
{
// Bessel I0 over [15, 50]
// Maximum Deviation Found: 2.444e-20
// Expected Error Term : 2.438e-20
// Maximum Relative Change in Control Points : 2.101e-03
// Max Error found at float80 precision = Poly : 6.029974e-20
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401431675205845e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.49603355149968887210170e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, -4.67510486284376330257260e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, -4.09071458907089270559464e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, -5.75278280327696940044714e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.10591299500956620739254e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, -2.77061766699949309115618e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, -5.42683771801837596371638e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, -9.17021412070404158464316e+00),
BOOST_MATH_BIG_CONSTANT(T, 64, 1.04154379346763380543310e+02),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.43462345357478348323006e+03),
BOOST_MATH_BIG_CONSTANT(T, 64, 9.98109660274422449523837e+03),
BOOST_MATH_BIG_CONSTANT(T, 64, -3.74438822767781410362757e+04)
};
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
}
else
{
// Bessel I0 over[100, INF]
// Max error in interpolated form: 2.456e-20
// Max Error found at float80 precision = Poly: 5.446356e-20
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401432677958445e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.49603355150537411254359e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, -4.67510484842456251368526e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, -4.09071676503922479645155e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, -5.75256179814881566010606e-02),
BOOST_MATH_BIG_CONSTANT(T, 64, -1.10754910257965227825040e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, -2.67858639515616079840294e-01),
BOOST_MATH_BIG_CONSTANT(T, 64, -9.17266479586791298924367e-01)
};
T ex = exp(x / 2);
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
result *= ex;
return result;
}
}
template <typename T>
T bessel_i1_imp(const T& x, const mpl::int_<113>&)
{
BOOST_MATH_STD_USING
if(x < 7.75)
{
// Bessel I0 over[10 ^ -34, 7.75]
// Max error in interpolated form: 1.835e-35
// Max Error found at float128 precision = Poly: 1.645036e-34
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 113, 8.3333333333333333333333333333333331804098e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444444444444444444445418303082e-03),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.4722222222222222222222222222119082346591e-04),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.1574074074074074074074074078415867655987e-05),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.7557319223985890652557318255143448192453e-07),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.9209498614260519022423916850415000626427e-09),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.8346525853139609753354247043900442393686e-11),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266233060080535940234144302217e-13),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.9036894801151120925605467963949641957095e-15),
BOOST_MATH_BIG_CONSTANT(T, 113, 5.2300677879659941472662086395055636394839e-17),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.3526075563884539394691458717439115962233e-19),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.8420920639497841692288943167036233338434e-21),
BOOST_MATH_BIG_CONSTANT(T, 113, 8.7718669711748690065381181691546032291365e-24),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.6549445715236427401845636880769861424730e-26),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.3437296196812697924703896979250126739676e-28),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.3912734588619073883015937023564978854893e-31),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.2839967682792395867255384448052781306897e-33),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.3790094235693528861015312806394354114982e-36),
BOOST_MATH_BIG_CONSTANT(T, 113, 8.0423861671932104308662362292359563970482e-39),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.7493858979396446292135661268130281652945e-41),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.2786079392547776769387921361408303035537e-44),
BOOST_MATH_BIG_CONSTANT(T, 113, 8.2335693685833531118863552173880047183822e-47)
};
T a = x * x / 4;
T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
}
else if(x < 11)
{
// Max error in interpolated form: 8.574e-36
// Maximum Deviation Found : 4.689e-36
// Expected Error Term : 3.760e-36
// Maximum Relative Change in Control Points : 5.204e-03
// Max Error found at float128 precision = Poly : 2.882561e-34
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 113, 8.333333333333333326889717360850080939e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.944444444444444511272790848815114507e-03),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.472222222222221892451965054394153443e-04),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.157407407407408437378868534321538798e-05),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.755731922398566216824909767320161880e-07),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.920949861426434829568192525456800388e-09),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.834652585308926245465686943255486934e-11),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.594058428179852047689599244015979196e-13),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.903689479655006062822949671528763738e-15),
BOOST_MATH_BIG_CONSTANT(T, 113, 5.230067791254403974475987777406992984e-17),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.352607536815161679702105115200693346e-19),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.842092161364672561828681848278567885e-21),
BOOST_MATH_BIG_CONSTANT(T, 113, 8.771862912600611801856514076709932773e-24),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.654958704184380914803366733193713605e-26),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.343688672071130980471207297730607625e-28),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.392252844664709532905868749753463950e-31),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.282086786672692641959912811902298600e-33),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.408812012322547015191398229942864809e-36),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.681220437734066258673404589233009892e-39),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.072417451640733785626701738789290055e-41),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.352218520142636864158849446833681038e-44),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.407918492276267527897751358794783640e-46)
};
T a = x * x / 4;
T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
}
else if(x < 15)
{
//Max error in interpolated form: 7.599e-36
// Maximum Deviation Found : 1.766e-35
// Expected Error Term : 1.021e-35
// Maximum Relative Change in Control Points : 6.228e-03
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 113, 8.333333333333255774414858563409941233e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.944444444444897867884955912228700291e-03),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.472222222220954970397343617150959467e-04),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.157407407409660682751155024932538578e-05),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.755731922369973706427272809014190998e-07),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.920949861702265600960449699129258153e-09),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.834652583208361401197752793379677147e-11),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.594058441128280500819776168239988143e-13),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.903689413939268702265479276217647209e-15),
BOOST_MATH_BIG_CONSTANT(T, 113, 5.230068069012898202890718644753625569e-17),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.352606552027491657204243201021677257e-19),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.842095100698532984651921750204843362e-21),
BOOST_MATH_BIG_CONSTANT(T, 113, 8.771789051329870174925649852681844169e-24),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.655114381199979536997025497438385062e-26),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.343415732516712339472538688374589373e-28),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.396177019032432392793591204647901390e-31),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.277563309255167951005939802771456315e-33),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.449201419305514579791370198046544736e-36),
BOOST_MATH_BIG_CONSTANT(T, 113, 7.415430703400740634202379012388035255e-39),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.195458831864936225409005027914934499e-41),
BOOST_MATH_BIG_CONSTANT(T, 113, 8.829726762743879793396637797534668039e-45),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.698302711685624490806751012380215488e-46),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.062520475425422618494185821587228317e-49),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.732372906742845717148185173723304360e-52)
};
T a = x * x / 4;
T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
}
else if(x < 20)
{
// Max error in interpolated form: 8.864e-36
// Max Error found at float128 precision = Poly: 8.522841e-35
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422793693152031514179994954750043e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.496029423752889591425633234009799670e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -4.682975926820553021482820043377990241e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -3.138871171577224532369979905856458929e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -8.765350219426341341990447005798111212e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, 5.321389275507714530941178258122955540e+01),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.727748393898888756515271847678850411e+03),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.123040820686242586086564998713862335e+05),
BOOST_MATH_BIG_CONSTANT(T, 113, -3.784112378374753535335272752884808068e+06),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.054920416060932189433079126269416563e+08),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.450129415468060676827180524327749553e+09),
BOOST_MATH_BIG_CONSTANT(T, 113, 4.758831882046487398739784498047935515e+10),
BOOST_MATH_BIG_CONSTANT(T, 113, -7.736936520262204842199620784338052937e+11),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.051128683324042629513978256179115439e+13),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.188008285959794869092624343537262342e+14),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.108530004906954627420484180793165669e+15),
BOOST_MATH_BIG_CONSTANT(T, 113, -8.441516828490144766650287123765318484e+15),
BOOST_MATH_BIG_CONSTANT(T, 113, 5.158251664797753450664499268756393535e+16),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.467314522709016832128790443932896401e+17),
BOOST_MATH_BIG_CONSTANT(T, 113, 8.896222045367960462945885220710294075e+17),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.273382139594876997203657902425653079e+18),
BOOST_MATH_BIG_CONSTANT(T, 113, 3.669871448568623680543943144842394531e+18),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.813923031370708069940575240509912588e+18)
};
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
}
else if(x < 35)
{
// Max error in interpolated form: 6.028e-35
// Max Error found at float128 precision = Poly: 1.368313e-34
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422804012941975429616956496046931e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.496033550576049830976679315420681402e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -4.675107835141866009896710750800622147e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -4.090104965125365961928716504473692957e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -5.842241652296980863361375208605487570e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.063604828033747303936724279018650633e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -9.113375972811586130949401996332817152e+00),
BOOST_MATH_BIG_CONSTANT(T, 113, 6.334748570425075872639817839399823709e+02),
BOOST_MATH_BIG_CONSTANT(T, 113, -3.759150758768733692594821032784124765e+04),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.863672813448915255286274382558526321e+06),
BOOST_MATH_BIG_CONSTANT(T, 113, -7.798248643371718775489178767529282534e+07),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.769963173932801026451013022000669267e+09),
BOOST_MATH_BIG_CONSTANT(T, 113, -8.381780137198278741566746511015220011e+10),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.163891337116820832871382141011952931e+12),
BOOST_MATH_BIG_CONSTANT(T, 113, -4.764325864671438675151635117936912390e+13),
BOOST_MATH_BIG_CONSTANT(T, 113, 8.925668307403332887856809510525154955e+14),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.416692606589060039334938090985713641e+16),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.892398600219306424294729851605944429e+17),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.107232903741874160308537145391245060e+18),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.930223393531877588898224144054112045e+19),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.427759576167665663373350433236061007e+20),
BOOST_MATH_BIG_CONSTANT(T, 113, 8.306019279465532835530812122374386654e+20),
BOOST_MATH_BIG_CONSTANT(T, 113, -3.653753000392125229440044977239174472e+21),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.140760686989511568435076842569804906e+22),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.249149337812510200795436107962504749e+22),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.101619088427348382058085685849420866e+22)
};
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
}
else if(x < 100)
{
// Max error in interpolated form: 5.494e-35
// Max Error found at float128 precision = Poly: 1.214651e-34
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422804014326779399307367861631577e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.496033551505372542086590873271571919e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -4.675104848454290286276466276677172664e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -4.090716742397105403027549796269213215e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -5.752570419098513588311026680089351230e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.107369803696534592906420980901195808e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.699214194000085622941721628134575121e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -7.953006169077813678478720427604462133e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.746618809476524091493444128605380593e+00),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.084446249943196826652788161656973391e+01),
BOOST_MATH_BIG_CONSTANT(T, 113, -5.020325182518980633783194648285500554e+01),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.510195971266257573425196228564489134e+02),
BOOST_MATH_BIG_CONSTANT(T, 113, -5.241661863814900938075696173192225056e+03),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.323374362891993686413568398575539777e+05),
BOOST_MATH_BIG_CONSTANT(T, 113, -4.112838452096066633754042734723911040e+06),
BOOST_MATH_BIG_CONSTANT(T, 113, 9.369270194978310081563767560113534023e+07),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.704295412488936504389347368131134993e+09),
BOOST_MATH_BIG_CONSTANT(T, 113, 2.320829576277038198439987439508754886e+10),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.258818139077875493434420764260185306e+11),
BOOST_MATH_BIG_CONSTANT(T, 113, 1.396791306321498426110315039064592443e+12),
BOOST_MATH_BIG_CONSTANT(T, 113, -4.217617301585849875301440316301068439e+12)
};
return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
}
else
{
// Bessel I0 over[100, INF]
// Max error in interpolated form: 6.081e-35
// Max Error found at float128 precision = Poly: 1.407151e-34
static const T P[] = {
BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793994605993438200208417e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.4960335515053725422747977247811372936584e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -4.6751048484542891946087411826356811991039e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -4.0907167423975030452875828826630006305665e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -5.7525704189964886494791082898669060345483e-02),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.1073698056568248642163476807108190176386e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.6992139012879749064623499618582631684228e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -7.9530409594026597988098934027440110587905e-01),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.7462844478733532517044536719240098183686e+00),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.0870711340681926669381449306654104739256e+01),
BOOST_MATH_BIG_CONSTANT(T, 113, -4.8510175413216969245241059608553222505228e+01),
BOOST_MATH_BIG_CONSTANT(T, 113, -2.4094682286011573747064907919522894740063e+02),
BOOST_MATH_BIG_CONSTANT(T, 113, -1.3128845936764406865199641778959502795443e+03),
BOOST_MATH_BIG_CONSTANT(T, 113, -8.1655901321962541203257516341266838487359e+03),
BOOST_MATH_BIG_CONSTANT(T, 113, -3.8019591025686295090160445920753823994556e+04),
BOOST_MATH_BIG_CONSTANT(T, 113, -6.7008089049178178697338128837158732831105e+05)
};
T ex = exp(x / 2);
T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
result *= ex;
return result;
}
}
template <typename T>
T bessel_i1_imp(const T& x, const mpl::int_<0>&)
{
if(boost::math::tools::digits<T>() <= 24)
return bessel_i1_imp(x, mpl::int_<24>());
else if(boost::math::tools::digits<T>() <= 53)
return bessel_i1_imp(x, mpl::int_<53>());
else if(boost::math::tools::digits<T>() <= 64)
return bessel_i1_imp(x, mpl::int_<64>());
else if(boost::math::tools::digits<T>() <= 113)
return bessel_i1_imp(x, mpl::int_<113>());
BOOST_ASSERT(0);
return 0;
}
template <typename T>
inline T bessel_i1(const T& x)
{
typedef mpl::int_<
std::numeric_limits<T>::digits == 0 ?
0 :
std::numeric_limits<T>::digits <= 24 ?
24 :
std::numeric_limits<T>::digits <= 53 ?
53 :
std::numeric_limits<T>::digits <= 64 ?
64 :
std::numeric_limits<T>::digits <= 113 ?
113 : -1
> tag_type;
bessel_i1_initializer<T, tag_type>::force_instantiate();
return bessel_i1_imp(x, tag_type());
}
}}} // namespaces
#endif // BOOST_MATH_BESSEL_I1_HPP

View File

@@ -0,0 +1,451 @@
// 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
#ifdef _MSC_VER
#pragma once
#endif
#include <boost/math/special_functions/round.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 {
template <class T, class Policy>
struct cyl_bessel_i_small_z
{
typedef T result_type;
cyl_bessel_i_small_z(T v_, T z_) : k(0), v(v_), mult(z_*z_/4)
{
BOOST_MATH_STD_USING
term = 1;
}
T operator()()
{
T result = term;
++k;
term *= mult / k;
term /= k + v;
return result;
}
private:
unsigned k;
T v;
T term;
T mult;
};
template <class T, class Policy>
inline T bessel_i_small_z_series(T v, T x, const Policy& pol)
{
BOOST_MATH_STD_USING
T prefix;
if(v < max_factorial<T>::value)
{
prefix = pow(x / 2, v) / boost::math::tgamma(v + 1, pol);
}
else
{
prefix = v * log(x / 2) - boost::math::lgamma(v + 1, pol);
prefix = exp(prefix);
}
if(prefix == 0)
return prefix;
cyl_bessel_i_small_z<T, Policy> s(v, x);
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
T zero = 0;
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
#else
T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
#endif
policies::check_series_iterations<T>("boost::math::bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
return prefix * result;
}
// 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 = boost::math::tgamma1pm1(v, pol);
T gm = boost::math::tgamma1pm1(-v, pol);
a = log(x / 2);
b = exp(v * a);
sigma = -a * v;
c = abs(v) < tools::epsilon<T>() ?
T(1) : T(boost::math::sin_pi(v) / (v * pi<T>()));
d = abs(sigma) < tools::epsilon<T>() ?
T(1) : T(sinh(sigma) / sigma);
gamma1 = abs(v) < tools::epsilon<T>() ?
T(-euler<T>()) : 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;
BOOST_MATH_INSTRUMENT_VARIABLE(p);
BOOST_MATH_INSTRUMENT_VARIABLE(q);
BOOST_MATH_INSTRUMENT_VARIABLE(f);
BOOST_MATH_INSTRUMENT_VARIABLE(sigma);
BOOST_MATH_INSTRUMENT_CODE(sinh(sigma));
BOOST_MATH_INSTRUMENT_VARIABLE(gamma1);
BOOST_MATH_INSTRUMENT_VARIABLE(gamma2);
BOOST_MATH_INSTRUMENT_VARIABLE(c);
BOOST_MATH_INSTRUMENT_VARIABLE(d);
BOOST_MATH_INSTRUMENT_VARIABLE(a);
// 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<T>("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<T>("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;
//
// Under some circumstances q can grow very small and C very
// large, leading to under/overflow. This is particularly an
// issue for types which have many digits precision but a narrow
// exponent range. A typical example being a "double double" type.
// To avoid this situation we can normalise q (and related prev/current)
// and C. All other variables remain unchanged in value. A typical
// test case occurs when x is close to 2, for example cyl_bessel_k(9.125, 2.125).
//
if(q < tools::epsilon<T>())
{
C *= q;
prev /= q;
current /= q;
q = 1;
}
// S converges slower than f
BOOST_MATH_INSTRUMENT_VARIABLE(Q * delta);
BOOST_MATH_INSTRUMENT_VARIABLE(abs(S) * tolerance);
BOOST_MATH_INSTRUMENT_VARIABLE(S);
if (abs(Q * delta) < abs(S) * tolerance)
{
break;
}
}
policies::check_series_iterations<T>("boost::math::bessel_ik<%1%>(%1%,%1%) in CF2_ik", k, pol);
if(x >= tools::log_max_value<T>())
*Kv = exp(0.5f * log(pi<T>() / (2 * x)) - x - log(S));
else
*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;
int org_kind = kind;
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 = iround(v, pol);
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 = boost::math::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
}
BOOST_MATH_INSTRUMENT_VARIABLE(Ku);
BOOST_MATH_INSTRUMENT_VARIABLE(Ku1);
prev = Ku;
current = Ku1;
T scale = 1;
T scale_sign = 1;
for (k = 1; k <= n; k++) // forward recurrence for K
{
T fact = 2 * (u + k) / x;
if((tools::max_value<T>() - fabs(prev)) / fact < fabs(current))
{
prev /= current;
scale /= current;
scale_sign *= boost::math::sign(current);
current = 1;
}
next = fact * current + prev;
prev = current;
current = next;
}
Kv = prev;
Kv1 = current;
BOOST_MATH_INSTRUMENT_VARIABLE(Kv);
BOOST_MATH_INSTRUMENT_VARIABLE(Kv1);
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 if((v > 0) && (x / v < 0.25))
{
Iv = bessel_i_small_z_series(v, x, pol);
}
else
{
CF1_ik(v, x, &fv, pol); // continued fraction CF1_ik
Iv = scale * 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);
T fact = (2 / pi<T>()) * (boost::math::sin_pi(z) * Kv);
if(fact == 0)
*I = Iv;
else if(tools::max_value<T>() * scale < fact)
*I = (org_kind & need_i) ? T(sign(fact) * scale_sign * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
else
*I = Iv + fact / scale; // reflection formula
}
else
{
*I = Iv;
}
if(tools::max_value<T>() * scale < Kv)
*K = (org_kind & need_k) ? T(sign(Kv) * scale_sign * policies::raise_overflow_error<T>(function, 0, pol)) : T(0);
else
*K = Kv / scale;
BOOST_MATH_INSTRUMENT_VARIABLE(*I);
BOOST_MATH_INSTRUMENT_VARIABLE(*K);
return 0;
}
}}} // namespaces
#endif // BOOST_MATH_BESSEL_IK_HPP

View File

@@ -0,0 +1,193 @@
// 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
#ifdef _MSC_VER
#pragma once
#endif
#include <boost/math/constants/constants.hpp>
#include <boost/math/tools/rational.hpp>
#include <boost/math/tools/big_constant.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);
template <class T>
struct bessel_j0_initializer
{
struct init
{
init()
{
do_init();
}
static void do_init()
{
bessel_j0(T(1));
}
void force_instantiate()const{}
};
static const init initializer;
static void force_instantiate()
{
initializer.force_instantiate();
}
};
template <class T>
const typename bessel_j0_initializer<T>::init bessel_j0_initializer<T>::initializer;
template <typename T>
T bessel_j0(T x)
{
bessel_j0_initializer<T>::force_instantiate();
static const T P1[] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -4.1298668500990866786e+11)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.7282507878605942706e+10)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -6.2140700423540120665e+08)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.6302997904833794242e+06)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.6629814655107086448e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0344222815443188943e+02)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2117036164593528341e-01))
};
static const T Q1[] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.3883787996332290397e+12)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.6328198300859648632e+10)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.3985097372263433271e+08)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.5612696224219938200e+05)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.3614022392337710626e+02)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 0.0))
};
static const T P2[] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8319397969392084011e+03)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2254078161378989535e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -7.2879702464464618998e+03)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0341910641583726701e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1725046279757103576e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.4176707025325087628e+03)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.4321196680624245801e+02)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.8591703355916499363e+01))
};
static const T Q2[] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -3.5783478026152301072e+05)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.4599102262586308984e+05)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.4055062591169562211e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.8680990008359188352e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.9458766545509337327e+03)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.3307310774649071172e+02)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.5258076240801555057e+01)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
};
static const T PC[] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2779090197304684302e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1345386639580765797e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1170523380864944322e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.4806486443249270347e+03)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.5376201909008354296e+02)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 8.8961548424210455236e-01))
};
static const T QC[] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.2779090197304684318e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 4.1370412495510416640e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.1215350561880115730e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 3.5028735138235608207e+03)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.5711159858080893649e+02)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
};
static const T PS[] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.9226600200800094098e+01)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.8591953644342993800e+02)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.1183429920482737611e+02)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -2.2300261666214198472e+01)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.2441026745835638459e+00)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -8.8033303048680751817e-03))
};
static const T QS[] = {
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.7105024128512061905e+03)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.1951131543434613647e+04)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 7.2642780169211018836e+03)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4887231232283756582e+03)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 9.0593769594993125859e+01)),
static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.0))
};
static const T x1 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 2.4048255576957727686e+00)),
x2 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.5200781102863106496e+00)),
x11 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 6.160e+02)),
x12 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, -1.42444230422723137837e-03)),
x21 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 1.4130e+03)),
x22 = static_cast<T>(BOOST_MATH_BIG_CONSTANT(T, 64, 5.46860286310649596604e-04));
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;
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 = constants::one_div_root_pi<T>() / sqrt(x);
//
// What follows is really just:
//
// T z = x - pi/4;
// value = factor * (rc * cos(z) - y * rs * sin(z));
//
// But using the addition formulae for sin and cos, plus
// the special values for sin/cos of pi/4.
//
T sx = sin(x);
T cx = cos(x);
value = factor * (rc * (cx + sx) - y * rs * (sx - cx));
}
return value;
}
}}} // namespaces
#endif // BOOST_MATH_BESSEL_J0_HPP

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