$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: john_at_[hidden]
Date: 2008-05-08 13:14:18
Author: johnmaddock
Date: 2008-05-08 13:14:17 EDT (Thu, 08 May 2008)
New Revision: 45220
URL: http://svn.boost.org/trac/boost/changeset/45220
Log:
Made float_distance return a signed value.
Added docs for float_next etc.
Updated test_next to cope with signed results.
Added informational output to test_tr1.
Added:
   sandbox/math_toolkit/libs/math/doc/sf_and_dist/float_next.qbk   (contents, props changed)
Text files modified: 
   sandbox/math_toolkit/boost/math/special_functions/next.hpp |    12 +++++++-----                            
   sandbox/math_toolkit/libs/math/doc/sf_and_dist/math.qbk    |     1 +                                       
   sandbox/math_toolkit/libs/math/test/test_next.cpp          |    16 ++++++++++------                        
   sandbox/math_toolkit/libs/math/test/test_tr1.cpp           |     5 +++++                                   
   4 files changed, 23 insertions(+), 11 deletions(-)
Modified: sandbox/math_toolkit/boost/math/special_functions/next.hpp
==============================================================================
--- sandbox/math_toolkit/boost/math/special_functions/next.hpp	(original)
+++ sandbox/math_toolkit/boost/math/special_functions/next.hpp	2008-05-08 13:14:17 EDT (Thu, 08 May 2008)
@@ -174,21 +174,23 @@
    //
    // Special cases:
    //
+   if(a > b)
+      return -float_distance(b, a);
    if(a == b)
       return 0;
    if(a == 0)
-      return 1 + float_distance(boost::math::sign(b) * detail::get_smallest_value<T>(), b, pol);
+      return 1 + fabs(float_distance(boost::math::sign(b) * detail::get_smallest_value<T>(), b, pol));
    if(b == 0)
-      return 1 + float_distance(boost::math::sign(a) * detail::get_smallest_value<T>(), a, pol);
+      return 1 + fabs(float_distance(boost::math::sign(a) * detail::get_smallest_value<T>(), a, pol));
    if(boost::math::sign(a) != boost::math::sign(b))
-      return 2 + float_distance(boost::math::sign(b) * detail::get_smallest_value<T>(), b, pol)
-         + float_distance(boost::math::sign(a) * detail::get_smallest_value<T>(), a, pol);
+      return 2 + fabs(float_distance(boost::math::sign(b) * detail::get_smallest_value<T>(), b, pol))
+         + fabs(float_distance(boost::math::sign(a) * detail::get_smallest_value<T>(), a, pol));
 
    if((std::min)(fabs(a), fabs(b)) / (std::max)(fabs(a), fabs(b)) < 2 * tools::epsilon<T>())
    {
       bool biga = fabs(a) > fabs(b);
       T split = ldexp(biga ? b : a, tools::digits<T>() - 2);
-      return float_distance(a, split, pol) + float_distance(split, b, pol);
+      return fabs(float_distance(a, split, pol) + float_distance(split, b, pol));
    }
 
    BOOST_MATH_STD_USING
Added: sandbox/math_toolkit/libs/math/doc/sf_and_dist/float_next.qbk
==============================================================================
--- (empty file)
+++ sandbox/math_toolkit/libs/math/doc/sf_and_dist/float_next.qbk	2008-05-08 13:14:17 EDT (Thu, 08 May 2008)
@@ -0,0 +1,118 @@
+[section:next_float Floating Point Representation Distance (ULP), 
+   and Moving Between Adjacent Floating Point Values]
+   
+[section:nextafter Moving to the Next Representable Value in 
+   a Specific Direction (nextafter)]
+   
+[h4 Synopsis]
+
+``
+#include <boost/math/special_functions/next.hpp>
+``
+
+   namespace boost{ namespace math{
+   
+   template <class T>
+   T nextafter(T val, T direction);
+   
+   }} // namespaces
+
+[h4 Description]
+
+This is an implementation of the `nextafter` function included in the C99 standard.
+
+Returns the next representable value after /x/ in the direction of /y/.  If
+`x == y` then returns /x/.  If /x/ is non-finite then returns the result of
+a __domain_error.  If there is no such value in the direction of /y/ then
+returns an __overflow_error.
+
+[endsect]
+
+[section:float_next Moving to the Next Greater Representable Value]
+   
+[h4 Synopsis]
+
+``
+#include <boost/math/special_functions/next.hpp>
+``
+
+   namespace boost{ namespace math{
+   
+   template <class T>
+   T float_next(T val);
+   
+   }} // namespaces
+
+[h4 Description]
+
+Returns the next representable value which is greater than /x/.  
+If /x/ is non-finite then returns the result of
+a __domain_error.  If there is no such value greater than /x/ then
+returns an __overflow_error.
+
+[endsect]
+
+[section:float_prior Moving to the Next Smaller Representable Value]
+   
+[h4 Synopsis]
+
+``
+#include <boost/math/special_functions/next.hpp>
+``
+
+   namespace boost{ namespace math{
+   
+   template <class T>
+   T float_prior(T val);
+   
+   }} // namespaces
+
+[h4 Description]
+
+Returns the next representable value which is less than /x/.  
+If /x/ is non-finite then returns the result of
+a __domain_error.  If there is no such value less than /x/ then
+returns an __overflow_error.
+
+[endsect]
+
+[section:float_distance Calculating the Representation Distance
+   Between Two Floating Point Values (ULP)]
+   
+[h4 Synopsis]
+
+``
+#include <boost/math/special_functions/next.hpp>
+``
+
+   namespace boost{ namespace math{
+   
+   template <class T>
+   T float_distance(T a, T b);
+   
+   }} // namespaces
+
+[h4 Description]
+
+Returns the distance between /a/ and /b/: the result is always an integer
+representing the number of distinct representations between /a/ and /b/.
+
+Note that `float_distance(a, a)` always returns 0,
+`float_distance(float_next(a), a)` always returns 1, and.
+`float_distance(float_prior(a), a)` always returns -1.
+
+The function `float_distance` is equivalent to calculating the number
+of ULP (Units in the Last Place) between /a/ and /b/ except that it 
+returns a signed value indicating whether `a > b` or not.
+
+[endsect]
+
+[endsect]
+
+[/ 
+  Copyright 2008 John Maddock and Paul A. Bristow.
+  Distributed under the Boost Software License, Version 1.0.
+  (See accompanying file LICENSE_1_0.txt or copy at
+  http://www.boost.org/LICENSE_1_0.txt).
+]
+
Modified: sandbox/math_toolkit/libs/math/doc/sf_and_dist/math.qbk
==============================================================================
--- sandbox/math_toolkit/libs/math/doc/sf_and_dist/math.qbk	(original)
+++ sandbox/math_toolkit/libs/math/doc/sf_and_dist/math.qbk	2008-05-08 13:14:17 EDT (Thu, 08 May 2008)
@@ -388,6 +388,7 @@
 [include inv_hyper.qbk]
 [include rounding_func.qbk]
 [include fpclassify.qbk]
+[include float_next.qbk]
 [endsect] [/section:special Special Functions]
 
 [section:toolkit Internal Details and Tools (Experimental)]
Modified: sandbox/math_toolkit/libs/math/test/test_next.cpp
==============================================================================
--- sandbox/math_toolkit/libs/math/test/test_next.cpp	(original)
+++ sandbox/math_toolkit/libs/math/test/test_next.cpp	2008-05-08 13:14:17 EDT (Thu, 08 May 2008)
@@ -8,6 +8,10 @@
 #include <boost/test/floating_point_comparison.hpp>
 #include <boost/math/special_functions/next.hpp>
 
+#ifdef BOOST_MSVC
+#pragma warning(disable:4127)
+#endif
+
 template <class T>
 void test_value(const T& val, const char* name)
 {
@@ -17,15 +21,15 @@
 
    std::cout << "Testing type " << name << " with initial value " << val << std::endl;
 
-   BOOST_CHECK_EQUAL(float_distance(float_next(val), val), 1);
+   BOOST_CHECK_EQUAL(float_distance(float_next(val), val), -1);
    BOOST_CHECK(float_next(val) > val);
    BOOST_CHECK_EQUAL(float_distance(float_prior(val), val), 1);
    BOOST_CHECK(float_prior(val) < val);
-   BOOST_CHECK_EQUAL(float_distance(nextafter(val, upper), val), 1);
+   BOOST_CHECK_EQUAL(float_distance(nextafter(val, upper), val), -1);
    BOOST_CHECK(nextafter(val, upper) > val);
    BOOST_CHECK_EQUAL(float_distance(nextafter(val, lower), val), 1);
    BOOST_CHECK(nextafter(val, lower) < val);
-   BOOST_CHECK_EQUAL(float_distance(float_next(float_next(val)), val), 2);
+   BOOST_CHECK_EQUAL(float_distance(float_next(float_next(val)), val), -2);
    BOOST_CHECK_EQUAL(float_distance(float_prior(float_prior(val)), val), 2);
    BOOST_CHECK_EQUAL(float_distance(float_prior(float_next(val)), val), 0);
    BOOST_CHECK_EQUAL(float_distance(float_next(float_prior(val)), val), 0);
@@ -64,7 +68,7 @@
       test_value(-2 * std::numeric_limits<T>::denorm_min(), name);
    }
 
-   static const unsigned primes[] = {
+   static const int primes[] = {
       11,     13,     17,     19,     23,     29, 
       31,     37,     41,     43,     47,     53,     59,     61,     67,     71, 
       73,     79,     83,     89,     97,    101,    103,    107,    109,    113, 
@@ -80,12 +84,12 @@
    {
       T v1 = val;
       T v2 = val;
-      for(unsigned j = 0; j < primes[i]; ++j)
+      for(int j = 0; j < primes[i]; ++j)
       {
          v1 = boost::math::float_next(v1);
          v2 = boost::math::float_prior(v2);
       }
-      BOOST_CHECK_EQUAL(boost::math::float_distance(v1, val), primes[i]);
+      BOOST_CHECK_EQUAL(boost::math::float_distance(v1, val), -primes[i]);
       BOOST_CHECK_EQUAL(boost::math::float_distance(v2, val), primes[i]);
    }
 }
Modified: sandbox/math_toolkit/libs/math/test/test_tr1.cpp
==============================================================================
--- sandbox/math_toolkit/libs/math/test/test_tr1.cpp	(original)
+++ sandbox/math_toolkit/libs/math/test/test_tr1.cpp	2008-05-08 13:14:17 EDT (Thu, 08 May 2008)
@@ -17,6 +17,7 @@
 
 void test_values(float, const char* name)
 {
+   std::cout << "Testing type " << name << std::endl;
    //
    // First the C99 math functions:
    //
@@ -648,6 +649,8 @@
 
 void test_values(double, const char* name)
 {
+   std::cout << "Testing type " << name << std::endl;
+
    double eps = boost::math::tools::epsilon<double>();
    BOOST_CHECK_CLOSE(tr1::acosh(std::cosh(0.5)), 0.5, 500 * eps);
    BOOST_CHECK_CLOSE(tr1::asinh(std::sinh(0.5)), 0.5, 500 * eps);
@@ -964,6 +967,8 @@
 
 void test_values(long double, const char* name)
 {
+   std::cout << "Testing type " << name << std::endl;
+
    long double eps = boost::math::tools::epsilon<long double>();
    BOOST_CHECK_CLOSE(tr1::acoshl(std::cosh(0.5L)), 0.5L, 5000 * eps);
    BOOST_CHECK_CLOSE(tr1::asinhl(std::sinh(0.5L)), 0.5L, 5000 * eps);