|
Boost-Commit : |
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);
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