Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r56370 - in trunk: boost/math/special_functions libs/math/doc/sf_and_dist libs/math/minimax libs/math/performance libs/math/test libs/regex/performance
From: john_at_[hidden]
Date: 2009-09-24 07:23:53


Author: johnmaddock
Date: 2009-09-24 07:23:52 EDT (Thu, 24 Sep 2009)
New Revision: 56370
URL: http://svn.boost.org/trac/boost/changeset/56370

Log:
Changes relating to issue #3408.
Add hooks for the dcdflib to the incomplete gamma tests.
Add hooks for the dcdflib to the igamma performance tests.
Some small performance enhancements.
Text files modified:
   trunk/boost/math/special_functions/gamma.hpp | 33 +++++++---
   trunk/libs/math/doc/sf_and_dist/igamma.qbk | 10 +-
   trunk/libs/math/minimax/f.cpp | 4
   trunk/libs/math/minimax/main.cpp | 6
   trunk/libs/math/performance/test_igamma.cpp | 121 ++++++++++++++++++++++++++++++++++++++++
   trunk/libs/math/test/test_gamma_hooks.hpp | 105 ++++++++++++++++++++++++++++++++++
   trunk/libs/math/test/test_igamma.cpp | 4
   trunk/libs/math/test/test_igamma_inv.cpp | 23 +++++++
   trunk/libs/regex/performance/Jamfile.v2 | 1
   9 files changed, 284 insertions(+), 23 deletions(-)

Modified: trunk/boost/math/special_functions/gamma.hpp
==============================================================================
--- trunk/boost/math/special_functions/gamma.hpp (original)
+++ trunk/boost/math/special_functions/gamma.hpp 2009-09-24 07:23:52 EDT (Thu, 24 Sep 2009)
@@ -733,22 +733,26 @@
 // Upper gamma fraction for very small a:
 //
 template <class T, class Policy>
-inline T tgamma_small_upper_part(T a, T x, const Policy& pol)
+inline T tgamma_small_upper_part(T a, T x, const Policy& pol, T* pgam = 0)
 {
    BOOST_MATH_STD_USING // ADL of std functions.
    //
    // Compute the full upper fraction (Q) when a is very small:
    //
    T result;
- result = boost::math::tgamma1pm1(a, pol) - boost::math::powm1(x, a, pol);
+ result = boost::math::tgamma1pm1(a, pol);
+ if(pgam)
+ *pgam = (result + 1) / a;
+ T p = boost::math::powm1(x, a, pol);
+ result -= p;
    result /= a;
    detail::small_gamma2_series<T> s(a, x);
    boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
    T zero = 0;
- result -= pow(x, a) * tools::sum_series(s, boost::math::policies::digits<T, Policy>(), max_iter, zero);
+ result -= (p + 1) * tools::sum_series(s, boost::math::policies::digits<T, Policy>(), max_iter, zero);
 #else
- result -= pow(x, a) * tools::sum_series(s, boost::math::policies::digits<T, Policy>(), max_iter);
+ result -= (p + 1) * tools::sum_series(s, boost::math::policies::digits<T, Policy>(), max_iter);
 #endif
    policies::check_series_iterations("boost::math::tgamma_small_upper_part<%1%>(%1%, %1%)", max_iter, pol);
    return result;
@@ -877,9 +881,10 @@
       {
          // Compute Q:
          invert = !invert;
- result = tgamma_small_upper_part(a, x, pol);
+ T g;
+ result = tgamma_small_upper_part(a, x, pol, &g);
          if(normalised)
- result /= boost::math::tgamma(a, pol);
+ result /= g;
          if(p_derivative)
             *p_derivative = regularised_gamma_prefix(a, x, pol, lanczos_type());
       }
@@ -887,9 +892,9 @@
    else if(x < 1.1)
    {
       //
- // Changover here occurs when P ~ 0.6 or Q ~ 0.4:
+ // Changover here occurs when P ~ 0.75 or Q ~ 0.25:
       //
- if(x * 1.1f < a)
+ if(x * 0.75f < a)
       {
          // Compute P:
          result = normalised ? regularised_gamma_prefix(a, x, pol, lanczos_type()) : full_igamma_prefix(a, x, pol);
@@ -902,9 +907,10 @@
       {
          // Compute Q:
          invert = !invert;
- result = tgamma_small_upper_part(a, x, pol);
+ T g;
+ result = tgamma_small_upper_part(a, x, pol, &g);
          if(normalised)
- result /= boost::math::tgamma(a, pol);
+ result /= g;
          if(p_derivative)
             *p_derivative = regularised_gamma_prefix(a, x, pol, lanczos_type());
       }
@@ -981,11 +987,14 @@
          // Regular case where the result will not be too close to 0.5.
          //
          // Changeover here occurs at P ~ Q ~ 0.5
+ // Note that series computation of P is about x2 faster than continued fraction
+ // calculation of Q, so try and use the CF only when really necessary, especially
+ // for small x.
          //
          result = normalised ? regularised_gamma_prefix(a, x, pol, lanczos_type()) : full_igamma_prefix(a, x, pol);
          if(p_derivative)
             *p_derivative = result;
- if(x < a)
+ if(x - (1 / (3 * x)) < a)
          {
             // Compute P:
             if(result != 0)
@@ -1001,6 +1010,8 @@
       }
    }
 
+ if(normalised && (result > 1))
+ result = 1;
    if(invert)
    {
       T gam = normalised ? 1 : boost::math::tgamma(a, pol);

Modified: trunk/libs/math/doc/sf_and_dist/igamma.qbk
==============================================================================
--- trunk/libs/math/doc/sf_and_dist/igamma.qbk (original)
+++ trunk/libs/math/doc/sf_and_dist/igamma.qbk 2009-09-24 07:23:52 EDT (Thu, 24 Sep 2009)
@@ -251,14 +251,14 @@
 4) [equation igamma8]
 
 Or by subtraction of the upper integral from either [Gamma](a) or 1
-when /x > a and x > 1.1/.
+when /x - (1/(3x)) > a and x > 1.1/.
 
 The upper integral is computed from Legendre's continued fraction representation:
 
 5) [equation igamma9]
 
-When /x > 1.1/ or by subtraction of the lower integral from either [Gamma](a) or 1
-when /x < a/.
+When /(x > 1.1)/ or by subtraction of the lower integral from either [Gamma](a) or 1
+when /x - (1/(3x)) < a/.
 
 For /x < 1.1/ computation of the upper integral is more complex as the continued
 fraction representation is unstable in this area. However there is another
@@ -279,9 +279,9 @@
 function in this region.
 
 For /x < 1.1/ the crossover point where the result is ~0.5 no longer
-occurs for /x ~ y/. Using /x * 1.1 < a/ as the crossover criterion
+occurs for /x ~ y/. Using /x * 0.75 < a/ as the crossover criterion
 for /0.5 < x <= 1.1/ keeps the maximum value computed (whether
-it's the upper or lower interval) to around 0.6. Likewise for
+it's the upper or lower interval) to around 0.75. Likewise for
 /x <= 0.5/ then using /-0.4 / log(x) < a/ as the crossover criterion
 keeps the maximum value computed to around 0.7
 (whether it's the upper or lower interval).

Modified: trunk/libs/math/minimax/f.cpp
==============================================================================
--- trunk/libs/math/minimax/f.cpp (original)
+++ trunk/libs/math/minimax/f.cpp 2009-09-24 07:23:52 EDT (Thu, 24 Sep 2009)
@@ -4,8 +4,8 @@
 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 
 #define L22
-#include "../tools/ntl_rr_lanczos.hpp"
-#include "../tools/ntl_rr_digamma.hpp"
+//#include "../tools/ntl_rr_lanczos.hpp"
+//#include "../tools/ntl_rr_digamma.hpp"
 #include <boost/math/bindings/rr.hpp>
 #include <boost/math/tools/polynomial.hpp>
 #include <boost/math/special_functions.hpp>

Modified: trunk/libs/math/minimax/main.cpp
==============================================================================
--- trunk/libs/math/minimax/main.cpp (original)
+++ trunk/libs/math/minimax/main.cpp 2009-09-24 07:23:52 EDT (Thu, 24 Sep 2009)
@@ -409,11 +409,11 @@
       std::string msg = "Max Error found at ";
       msg += name;
       msg += " precision = ";
- msg.append(62 - 17 - msg.size(), ' ');
+ //msg.append(62 - 17 - msg.size(), ' ');
       std::cout << msg << "Poly: " << std::setprecision(6)
- << std::setw(15) << std::left
+ //<< std::setw(15) << std::left
          << boost::math::tools::real_cast<T>(max_error)
- << "Cheb: " << boost::math::tools::real_cast<T>(max_cheb_error) << std::endl;
+ << " Cheb: " << boost::math::tools::real_cast<T>(max_cheb_error) << std::endl;
    }
    else
    {

Modified: trunk/libs/math/performance/test_igamma.cpp
==============================================================================
--- trunk/libs/math/performance/test_igamma.cpp (original)
+++ trunk/libs/math/performance/test_igamma.cpp 2009-09-24 07:23:52 EDT (Thu, 24 Sep 2009)
@@ -188,3 +188,124 @@
 }
 
 #endif
+
+#ifdef TEST_DCDFLIB
+#include <dcdflib.h>
+namespace dcd{
+
+inline double gamma_q(double x, double y)
+{
+ double ans, qans;
+ int i = 0;
+ gamma_inc (&x, &y, &ans, &qans, &i);
+ return qans;
+}
+
+inline double gamma_p(double x, double y)
+{
+ double ans, qans;
+ int i = 0;
+ gamma_inc (&x, &y, &ans, &qans, &i);
+ return ans;
+}
+
+inline double gamma_q_inv(double x, double y)
+{
+ double ans, p, nul;
+ int i = 0;
+ p = 1 - y;
+ nul = 0;
+ gamma_inc_inv (&x, &ans, &nul, &p, &y, &i);
+ return ans;
+}
+
+inline double gamma_p_inv(double x, double y)
+{
+ double ans, p, nul;
+ int i = 0;
+ p = 1 - y;
+ nul = 0;
+ gamma_inc_inv (&x, &ans, &nul, &y, &p, &i);
+ return ans;
+}
+
+}
+
+template <std::size_t N>
+double igamma_evaluate2_dcd(const boost::array<boost::array<T, 6>, N>& data)
+{
+ double result = 0;
+ for(unsigned i = 0; i < N; ++i)
+ {
+ result += dcd::gamma_p(data[i][0], data[i][1]);
+ result += dcd::gamma_q(data[i][0], data[i][1]);
+ }
+ return result;
+}
+
+BOOST_MATH_PERFORMANCE_TEST(igamma_test, "igamma-dcd")
+{
+ double result = igamma_evaluate2_dcd(igamma_big_data);
+ result += igamma_evaluate2_dcd(igamma_int_data);
+ result += igamma_evaluate2_dcd(igamma_med_data);
+ result += igamma_evaluate2_dcd(igamma_small_data);
+
+ consume_result(result);
+ set_call_count(
+ 2 * (sizeof(igamma_big_data)
+ + sizeof(igamma_int_data)
+ + sizeof(igamma_med_data)
+ + sizeof(igamma_small_data)) / sizeof(igamma_big_data[0]));
+}
+
+template <std::size_t N>
+double igamma_inv_evaluate2_dcd(const boost::array<boost::array<T, 6>, N>& data)
+{
+ double result = 0;
+ for(unsigned i = 0; i < N; ++i)
+ {
+ result += dcd::gamma_p_inv(data[i][0], data[i][5]);
+ result += dcd::gamma_q_inv(data[i][0], data[i][3]);
+ }
+ return result;
+}
+
+BOOST_MATH_PERFORMANCE_TEST(igamma_inv_test, "igamma_inv-dcd")
+{
+ double result = igamma_inv_evaluate2_dcd(igamma_big_data);
+ result += igamma_inv_evaluate2_dcd(igamma_int_data);
+ result += igamma_inv_evaluate2_dcd(igamma_med_data);
+ result += igamma_inv_evaluate2_dcd(igamma_small_data);
+
+ consume_result(result);
+ set_call_count(
+ 2 * (sizeof(igamma_big_data)
+ + sizeof(igamma_int_data)
+ + sizeof(igamma_med_data)
+ + sizeof(igamma_small_data)) / sizeof(igamma_big_data[0]));
+}
+
+#endif
+
+double x = 0.165048161769598689119220580323599278926849365234375e-11;
+double y = 0.165048164480104120332981665342231281101703643798828125e-13;
+
+BOOST_MATH_PERFORMANCE_TEST(igamma_scrap, "igamma_scrap")
+{
+ //double result = boost::math::gamma_q(x, y);
+ double result = igamma_evaluate2(igamma_small_data);
+ //result += dcd::gamma_p(x, y);
+
+ consume_result(result);
+ set_call_count(1);
+}
+
+BOOST_MATH_PERFORMANCE_TEST(igamma_scrap, "igamma_scrap-dcd")
+{
+ //double result = dcd::gamma_q(x, y);
+ double result = igamma_evaluate2_dcd(igamma_small_data);
+
+ consume_result(result);
+ set_call_count(1);
+}
+

Modified: trunk/libs/math/test/test_gamma_hooks.hpp
==============================================================================
--- trunk/libs/math/test/test_gamma_hooks.hpp (original)
+++ trunk/libs/math/test/test_gamma_hooks.hpp 2009-09-24 07:23:52 EDT (Thu, 24 Sep 2009)
@@ -162,12 +162,117 @@
 }
 #endif
 
+#ifdef TEST_DCDFLIB
+#define TEST_OTHER
+#include <dcdflib.h>
+
+namespace other{
+float tgamma(float z)
+{
+ double v = z;
+ return (float)gamma_x(&v);
+}
+double tgamma(double z)
+{
+ return gamma_x(&z);
+}
+long double tgamma(long double z)
+{
+ double v = z;
+ return gamma_x(&v);
+}
+float lgamma(float z)
+{
+ double v = z;
+ return (float)gamma_log(&v);
+}
+double lgamma(double z)
+{
+ double v = z;
+ return gamma_log(&v);
+}
+long double lgamma(long double z)
+{
+ double v = z;
+ return gamma_log(&v);
+}
+inline double gamma_q(double x, double y)
+{
+ double ans, qans;
+ int i = 0;
+ gamma_inc (&x, &y, &ans, &qans, &i);
+ return qans;
+}
+inline float gamma_q(float x, float y)
+{
+ return (float)gamma_q((double)x, (double)y);
+}
+inline long double gamma_q(long double x, long double y)
+{
+ return gamma_q((double)x, (double)y);
+}
+inline double gamma_p(double x, double y)
+{
+ double ans, qans;
+ int i = 0;
+ gamma_inc (&x, &y, &ans, &qans, &i);
+ return ans;
+}
+inline float gamma_p(float x, float y)
+{
+ return (float)gamma_p((double)x, (double)y);
+}
+inline long double gamma_p(long double x, long double y)
+{
+ return gamma_p((double)x, (double)y);
+}
+
+inline double gamma_q_inv(double x, double y)
+{
+ double ans, p, nul;
+ int i = 0;
+ p = 1 - y;
+ nul = 0;
+ gamma_inc_inv (&x, &ans, &nul, &p, &y, &i);
+ return ans;
+}
+inline float gamma_q_inv(float x, float y)
+{
+ return (float)gamma_q_inv((double)x, (double)y);
+}
+inline long double gamma_q_inv(long double x, long double y)
+{
+ return gamma_q_inv((double)x, (double)y);
+}
+inline double gamma_p_inv(double x, double y)
+{
+ double ans, p, nul;
+ int i = 0;
+ p = 1 - y;
+ nul = 0;
+ gamma_inc_inv (&x, &ans, &nul, &y, &p, &i);
+ return ans;
+}
+inline float gamma_p_inv(float x, float y)
+{
+ return (float)gamma_p_inv((double)x, (double)y);
+}
+inline long double gamma_p_inv(long double x, long double y)
+{
+ return gamma_p_inv((double)x, (double)y);
+}
+
+}
+#endif
+
 #ifdef TEST_OTHER
 namespace other{
    boost::math::concepts::real_concept tgamma(boost::math::concepts::real_concept){ return 0; }
    boost::math::concepts::real_concept lgamma(boost::math::concepts::real_concept){ return 0; }
    boost::math::concepts::real_concept gamma_q(boost::math::concepts::real_concept, boost::math::concepts::real_concept){ return 0; }
    boost::math::concepts::real_concept gamma_p(boost::math::concepts::real_concept, boost::math::concepts::real_concept){ return 0; }
+ boost::math::concepts::real_concept gamma_p_inv(boost::math::concepts::real_concept x, boost::math::concepts::real_concept y){ return 0; }
+ boost::math::concepts::real_concept gamma_q_inv(boost::math::concepts::real_concept x, boost::math::concepts::real_concept y){ return 0; }
 }
 #endif
 

Modified: trunk/libs/math/test/test_igamma.cpp
==============================================================================
--- trunk/libs/math/test/test_igamma.cpp (original)
+++ trunk/libs/math/test/test_igamma.cpp 2009-09-24 07:23:52 EDT (Thu, 24 Sep 2009)
@@ -361,7 +361,7 @@
       bind_func(funcp, 0, 1),
       extract_result(3));
    handle_test_result(result, data[result.worst()], result.worst(), type_name, "boost::math::gamma_q", test_name);
-#if defined(TEST_CEPHES) || defined(TEST_GSL)
+#if defined(TEST_OTHER)
    //
    // test other gamma_q(T, T) against data:
    //
@@ -388,7 +388,7 @@
       bind_func(funcp, 0, 1),
       extract_result(5));
    handle_test_result(result, data[result.worst()], result.worst(), type_name, "boost::math::gamma_p", test_name);
-#if defined(TEST_CEPHES) || defined(TEST_GSL)
+#if defined(TEST_OTHER)
    //
    // test other gamma_p(T, T) against data:
    //

Modified: trunk/libs/math/test/test_igamma_inv.cpp
==============================================================================
--- trunk/libs/math/test/test_igamma_inv.cpp (original)
+++ trunk/libs/math/test/test_igamma_inv.cpp 2009-09-24 07:23:52 EDT (Thu, 24 Sep 2009)
@@ -315,6 +315,29 @@
       bind_func(funcp, 0, 1),
       extract_result(3));
    handle_test_result(result, data[result.worst()], result.worst(), type_name, "boost::math::gamma_q_inv", test_name);
+#ifdef TEST_OTHER
+ if(boost::is_floating_point<value_type>::value)
+ {
+ funcp = other::gamma_p_inv;
+ //
+ // test gamma_p_inv(T, T) against data:
+ //
+ result = boost::math::tools::test(
+ data,
+ bind_func(funcp, 0, 1),
+ extract_result(2));
+ handle_test_result(result, data[result.worst()], result.worst(), type_name, "other::gamma_p_inv", test_name);
+ //
+ // test gamma_q_inv(T, T) against data:
+ //
+ funcp = other::gamma_q_inv;
+ result = boost::math::tools::test(
+ data,
+ bind_func(funcp, 0, 1),
+ extract_result(3));
+ handle_test_result(result, data[result.worst()], result.worst(), type_name, "other::gamma_q_inv", test_name);
+ }
+#endif
 }
 
 template <class T>

Modified: trunk/libs/regex/performance/Jamfile.v2
==============================================================================
--- trunk/libs/regex/performance/Jamfile.v2 (original)
+++ trunk/libs/regex/performance/Jamfile.v2 2009-09-24 07:23:52 EDT (Thu, 24 Sep 2009)
@@ -48,6 +48,7 @@
     ;
 
 
+install . : regex_comparison ;
 
 
 


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