Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r80118 - trunk/boost/math/distributions
From: pbristow_at_[hidden]
Date: 2012-08-21 13:39:52


Author: pbristow
Date: 2012-08-21 13:39:51 EDT (Tue, 21 Aug 2012)
New Revision: 80118
URL: http://svn.boost.org/trac/boost/changeset/80118

Log:
Added support for infinite degrees of freedom.

Correct some error messages (and made quantile produce the correct complemented version by forwarding the function string to the detail:: code).

There are still some confusing variable names.

Text files modified:
   trunk/boost/math/distributions/non_central_t.hpp | 130 ++++++++++++++++++++++++++++-----------
   1 files changed, 93 insertions(+), 37 deletions(-)

Modified: trunk/boost/math/distributions/non_central_t.hpp
==============================================================================
--- trunk/boost/math/distributions/non_central_t.hpp (original)
+++ trunk/boost/math/distributions/non_central_t.hpp 2012-08-21 13:39:51 EDT (Tue, 21 Aug 2012)
@@ -206,9 +206,13 @@
          T non_central_t_cdf(T v, T delta, T t, bool invert, const Policy& pol)
          {
             BOOST_MATH_STD_USING
+ if (boost::math::isinf(v))
+ { // Infinite degrees of freedom, so use normal distribution located at delta.
+ normal_distribution<T, Policy> n(delta, 1);
+ return cdf(n, t);
+ }
             //
- // For t < 0 we have to use reflect:
- //
+ // Otherwise, for t < 0 we have to use the reflection formula:
             if(t < 0)
             {
                t = -t;
@@ -219,11 +223,11 @@
             {
                // Approximate with a Student's T centred on delta,
                // the crossover point is based on eq 2.6 from
- // "A Comparison of Approximations To Persentiles of the
+ // "A Comparison of Approximations To Percentiles of the
                // Noncentral t-Distribution". H. Sahai and M. M. Ojeda,
                // Revista Investigacion Operacional Vol 21, No 2, 2000.
                // Original sources referenced in the above are:
- // "Some Approximations to the Persentage Points of the Noncentral
+ // "Some Approximations to the Percentage Points of the Noncentral
                // t-Distribution". C. van Eeden. International Statistical Review, 29, 4-31.
                // "Continuous Univariate Distributions". N.L. Johnson, S. Kotz and
                // N. Balkrishnan. 1995. John Wiley and Sons New York.
@@ -274,7 +278,7 @@
                   result = non_central_t2_q(v, delta, x, y, pol, result);
                   result /= 2;
                }
- else
+ else // x == 0
                   result = cdf(complement(boost::math::normal_distribution<T, Policy>(), -delta));
             }
             if(invert)
@@ -283,10 +287,11 @@
          }
 
          template <class T, class Policy>
- T non_central_t_quantile(T v, T delta, T p, T q, const Policy&)
+ T non_central_t_quantile(const char* function, T v, T delta, T p, T q, const Policy&)
          {
             BOOST_MATH_STD_USING
- static const char* function = "quantile(non_central_t_distribution<%1%>, %1%)";
+ // static const char* function = "quantile(non_central_t_distribution<%1%>, %1%)";
+ // now passed as function
             typedef typename policies::evaluation<T, Policy>::type value_type;
             typedef typename policies::normalise<
                Policy,
@@ -296,7 +301,7 @@
                policies::assert_undefined<> >::type forwarding_policy;
 
                T r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
                   function,
                   v, &r, Policy())
                   ||
@@ -313,9 +318,22 @@
                   Policy()))
                      return r;
 
+
             value_type guess = 0;
- if(v > 3)
- {
+ if (boost::math::isinf(v))
+ { // Infinite degrees of freedom, so use normal distribution located at delta.
+ normal_distribution<T, Policy> n(delta, 1);
+ if (p < q)
+ {
+ return quantile(n, p);
+ }
+ else
+ {
+ return quantile(complement(n, q));
+ }
+ }
+ else if(v > 3)
+ { // Use normal distribution to calculate guess.
                value_type mean = delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f));
                value_type var = ((delta * delta + 1) * v) / (v - 2) - mean * mean;
                if(p < q)
@@ -429,9 +447,13 @@
          T non_central_t_pdf(T n, T delta, T t, const Policy& pol)
          {
             BOOST_MATH_STD_USING
+ if (boost::math::isinf(n))
+ { // Infinite degrees of freedom, so use normal distribution located at delta.
+ normal_distribution<T, Policy> n(delta, 1);
+ return pdf(n, t);
+ }
             //
- // For t < 0 we have to use the reflection formula:
- //
+ // Otherwise, for t < 0 we have to use the reflection formula:
             if(t < 0)
             {
                t = -t;
@@ -457,11 +479,11 @@
             {
                // Approximate with a Student's T centred on delta,
                // the crossover point is based on eq 2.6 from
- // "A Comparison of Approximations To Persentiles of the
+ // "A Comparison of Approximations To Percentiles of the
                // Noncentral t-Distribution". H. Sahai and M. M. Ojeda,
                // Revista Investigacion Operacional Vol 21, No 2, 2000.
                // Original sources referenced in the above are:
- // "Some Approximations to the Persentage Points of the Noncentral
+ // "Some Approximations to the Percentage Points of the Noncentral
                // t-Distribution". C. van Eeden. International Statistical Review, 29, 4-31.
                // "Continuous Univariate Distributions". N.L. Johnson, S. Kotz and
                // N. Balkrishnan. 1995. John Wiley and Sons New York.
@@ -493,6 +515,10 @@
          template <class T, class Policy>
          T mean(T v, T delta, const Policy& pol)
          {
+ if (boost::math::isinf(v))
+ {
+ return delta;
+ }
             BOOST_MATH_STD_USING
             return delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f), pol);
          }
@@ -500,6 +526,11 @@
          template <class T, class Policy>
          T variance(T v, T delta, const Policy& pol)
          {
+ if (boost::math::isinf(v))
+ {
+ return 1;
+ }
+
             T result = ((delta * delta + 1) * v) / (v - 2);
             T m = mean(v, delta, pol);
             result -= m * m;
@@ -510,6 +541,10 @@
          T skewness(T v, T delta, const Policy& pol)
          {
             BOOST_MATH_STD_USING
+ if (boost::math::isinf(v))
+ {
+ return 0;
+ }
             T mean = boost::math::detail::mean(v, delta, pol);
             T l2 = delta * delta;
             T var = ((l2 + 1) * v) / (v - 2) - mean * mean;
@@ -524,6 +559,10 @@
          T kurtosis_excess(T v, T delta, const Policy& pol)
          {
             BOOST_MATH_STD_USING
+ if (boost::math::isinf(v))
+ {
+ return 3;
+ }
             T mean = boost::math::detail::mean(v, delta, pol);
             T l2 = delta * delta;
             T var = ((l2 + 1) * v) / (v - 2) - mean * mean;
@@ -625,7 +664,7 @@
                // 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%",
+ "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());
             }
             t_non_centrality_finder<RealType, Policy> f(v, x, p < q ? p : q, p < q ? false : true);
@@ -651,7 +690,7 @@
             return result;
          }
 #endif
- } // namespace detail
+ } // namespace detail ======================================================================
 
       template <class RealType = double, class Policy = policies::policy<> >
       class non_central_t_distribution
@@ -664,7 +703,7 @@
          {
             const char* function = "boost::math::non_central_t_distribution<%1%>::non_central_t_distribution(%1%,%1%)";
             RealType r;
- detail::check_df(
+ detail::check_df_gt0_to_inf(
                function,
                v, &r, Policy());
             detail::check_finite(
@@ -802,7 +841,7 @@
          RealType v = dist.degrees_of_freedom();
          RealType l = dist.non_centrality();
          RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
             function,
             v, &r, Policy())
             ||
@@ -840,7 +879,7 @@
          RealType v = dist.degrees_of_freedom();
          RealType l = dist.non_centrality();
          RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
             function,
             v, &r, Policy())
             ||
@@ -853,7 +892,7 @@
          if(v <= 1)
             return policies::raise_domain_error<RealType>(
                function,
- "The non central t distribution has no defined mean for degrees of freedom <= 1: got v=%1%.", v, Policy());
+ "The non-central t distribution has no defined mean for degrees of freedom <= 1: got v=%1%.", v, Policy());
          // return l * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, RealType(0.5f));
          return policies::checked_narrowing_cast<RealType, forwarding_policy>(
             detail::mean(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
@@ -875,7 +914,7 @@
          RealType v = dist.degrees_of_freedom();
          RealType l = dist.non_centrality();
          RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
             function,
             v, &r, Policy())
             ||
@@ -888,7 +927,7 @@
          if(v <= 2)
             return policies::raise_domain_error<RealType>(
                function,
- "The non central t distribution has no defined variance for degrees of freedom <= 2: got v=%1%.", v, Policy());
+ "The non-central t distribution has no defined variance for degrees of freedom <= 2: got v=%1%.", v, Policy());
          return policies::checked_narrowing_cast<RealType, forwarding_policy>(
             detail::variance(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
       }
@@ -910,7 +949,7 @@
          RealType v = dist.degrees_of_freedom();
          RealType l = dist.non_centrality();
          RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
             function,
             v, &r, Policy())
             ||
@@ -923,7 +962,7 @@
          if(v <= 3)
             return policies::raise_domain_error<RealType>(
                function,
- "The non central t distribution has no defined skewness for degrees of freedom <= 3: got v=%1%.", v, Policy());;
+ "The non-central t distribution has no defined skewness for degrees of freedom <= 3: got v=%1%.", v, Policy());;
          return policies::checked_narrowing_cast<RealType, forwarding_policy>(
             detail::skewness(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
       }
@@ -942,7 +981,7 @@
          RealType v = dist.degrees_of_freedom();
          RealType l = dist.non_centrality();
          RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
             function,
             v, &r, Policy())
             ||
@@ -955,7 +994,7 @@
          if(v <= 4)
             return policies::raise_domain_error<RealType>(
                function,
- "The non central t distribution has no defined kurtosis for degrees of freedom <= 4: got v=%1%.", v, Policy());;
+ "The non-central t distribution has no defined kurtosis for degrees of freedom <= 4: got v=%1%.", v, Policy());;
          return policies::checked_narrowing_cast<RealType, forwarding_policy>(
             detail::kurtosis_excess(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
       } // kurtosis_excess
@@ -969,7 +1008,7 @@
       template <class RealType, class Policy>
       inline RealType pdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& t)
       { // Probability Density/Mass Function.
- const char* function = "cdf(non_central_t_distribution<%1%>, %1%)";
+ const char* function = "pdf(non_central_t_distribution<%1%>, %1%)";
          typedef typename policies::evaluation<RealType, Policy>::type value_type;
          typedef typename policies::normalise<
             Policy,
@@ -981,7 +1020,7 @@
          RealType v = dist.degrees_of_freedom();
          RealType l = dist.non_centrality();
          RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
             function,
             v, &r, Policy())
             ||
@@ -1008,7 +1047,8 @@
       template <class RealType, class Policy>
       RealType cdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& x)
       {
- const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
+ const char* function = "boost::math::cdf(non_central_t_distribution<%1%>&, %1%)";
+// was const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
          typedef typename policies::evaluation<RealType, Policy>::type value_type;
          typedef typename policies::normalise<
             Policy,
@@ -1020,7 +1060,7 @@
          RealType v = dist.degrees_of_freedom();
          RealType l = dist.non_centrality();
          RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
             function,
             v, &r, Policy())
             ||
@@ -1036,10 +1076,17 @@
             &r,
             Policy()))
                return (RealType)r;
+ if (boost::math::isinf(v))
+ { // Infinite degrees of freedom, so use normal distribution located at delta.
+ normal_distribution<RealType, Policy> n(l, 1);
+ cdf(n, x);
+ //return cdf(normal_distribution<RealType, Policy>(l, 1), x);
+ }
 
          if(l == 0)
+ { // NO non-centrality, so use Student's t instead.
             return cdf(students_t_distribution<RealType, Policy>(v), x);
-
+ }
          return policies::checked_narrowing_cast<RealType, forwarding_policy>(
             detail::non_central_t_cdf(
                static_cast<value_type>(v),
@@ -1052,7 +1099,8 @@
       template <class RealType, class Policy>
       RealType cdf(const complemented2_type<non_central_t_distribution<RealType, Policy>, RealType>& c)
       { // Complemented Cumulative Distribution Function
- const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
+ // was const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
+ const char* function = "boost::math::cdf(const complement(non_central_t_distribution<%1%>&), %1%)";
          typedef typename policies::evaluation<RealType, Policy>::type value_type;
          typedef typename policies::normalise<
             Policy,
@@ -1064,9 +1112,9 @@
          non_central_t_distribution<RealType, Policy> const& dist = c.dist;
          RealType x = c.param;
          RealType v = dist.degrees_of_freedom();
- RealType l = dist.non_centrality();
+ RealType l = dist.non_centrality(); // aka delta
          RealType r;
- if(!detail::check_df(
+ if(!detail::check_df_gt0_to_inf(
             function,
             v, &r, Policy())
             ||
@@ -1083,9 +1131,15 @@
             Policy()))
                return (RealType)r;
 
+ if (boost::math::isinf(v))
+ { // Infinite degrees of freedom, so use normal distribution located at delta.
+ normal_distribution<RealType, Policy> n(l, 1);
+ return cdf(complement(n, x));
+ }
          if(l == 0)
+ { // zero non-centrality so use Student's t distribution.
             return cdf(complement(students_t_distribution<RealType, Policy>(v), x));
-
+ }
          return policies::checked_narrowing_cast<RealType, forwarding_policy>(
             detail::non_central_t_cdf(
                static_cast<value_type>(v),
@@ -1098,19 +1152,21 @@
       template <class RealType, class Policy>
       inline RealType quantile(const non_central_t_distribution<RealType, Policy>& dist, const RealType& p)
       { // Quantile (or Percent Point) function.
+ static const char* function = "quantile(const non_central_t_distribution<%1%>, %1%)";
          RealType v = dist.degrees_of_freedom();
          RealType l = dist.non_centrality();
- return detail::non_central_t_quantile(v, l, p, RealType(1-p), Policy());
+ return detail::non_central_t_quantile(function, v, l, p, RealType(1-p), Policy());
       } // quantile
 
       template <class RealType, class Policy>
       inline RealType quantile(const complemented2_type<non_central_t_distribution<RealType, Policy>, RealType>& c)
       { // Quantile (or Percent Point) function.
+ static const char* function = "quantile(const complement(non_central_t_distribution<%1%>, %1%))";
          non_central_t_distribution<RealType, Policy> const& dist = c.dist;
          RealType q = c.param;
          RealType v = dist.degrees_of_freedom();
          RealType l = dist.non_centrality();
- return detail::non_central_t_quantile(v, l, RealType(1-q), q, Policy());
+ return detail::non_central_t_quantile(function, v, l, RealType(1-q), q, Policy());
       } // quantile complement.
 
    } // namespace math


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk