|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r54997 - sandbox/SOC/2007/visualization/boost/svg_plot/detail
From: pbristow_at_[hidden]
Date: 2009-07-17 10:04:52
Author: pbristow
Date: 2009-07-17 10:04:52 EDT (Fri, 17 Jul 2009)
New Revision: 54997
URL: http://svn.boost.org/trac/boost/changeset/54997
Log:
Floating-point comparison routines added to svg_plot/detail/FP_compare.hpp
Text files modified:
sandbox/SOC/2007/visualization/boost/svg_plot/detail/FP_compare.hpp | 208 ++++++++++++++++-----------------------
1 files changed, 87 insertions(+), 121 deletions(-)
Modified: sandbox/SOC/2007/visualization/boost/svg_plot/detail/FP_compare.hpp
==============================================================================
--- sandbox/SOC/2007/visualization/boost/svg_plot/detail/FP_compare.hpp (original)
+++ sandbox/SOC/2007/visualization/boost/svg_plot/detail/FP_compare.hpp 2009-07-17 10:04:52 EDT (Fri, 17 Jul 2009)
@@ -1,46 +1,33 @@
-/*! \file FP_compare.hpp
- \brief Two types of floating-point comparison "Very close" and "Close enough" to a chosen tolerance.
- \details
- Derived from Boost.Test Copyright Gennadiy Rozental 2001-2007.
- See http://www.boost.org/libs/test for the Boost.Test library home page.
- Deliberately removed any treatment of percent to avoid further potential confusion!
- \date Mar 2009
- \author Paul A. Bristow
-*/
-
-// Copyright Paul A. Bristow 2008, 2009
+// Copyright Paul A. Bristow 2008
+// derived from Copyright Gennadiy Rozental 2001-2007.
// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_FLOATING_POINT_COMPARISON_HPP
-#define BOOST_FLOATING_POINT_COMPARISON_HPP
+// See http://www.boost.org/libs/test for the library home page.
+// Deliberately removed any treatment of percent!
-#include <boost/limits.hpp> // using std::numeric_limits
-#include <boost/math/tools/precision.hpp> // using max_value, min_value & epsilon for floating_point type.
+#ifndef BOOST_TEST_FLOATING_POINT_COMPARISON_HPP
+#define BOOST_TEST_FLOATING_POINT_COMPARISON_HPP
-//namespace boost
-//{
-// namespace math
-// {
+#include <boost/limits.hpp> // for std::numeric_limits
+#include <boost/math/tools/precision.hpp> // for max_value, min_value & epsilon for floating_point type;
// Check two floating-point values are close within a chosen tolerance.
-template<typename FPT> class close_to; // Default = double.
+template<typename FPT> class close_to;
// Check floating-point value is smaller than a chosen small value.
-template<typename FPT> class smallest; // Default = double.
+template<typename FPT> class smallest;
enum floating_point_comparison_type
-{ /*! \enum floating_point_comparison_type
- \brief Two types of floating-point comparison "Very close" and "Close enough".
- \details equations in Douglas E. Knuth, Seminumerical algorithms (3rd Ed) section 4.2.4, Vol II,
- pp 213-225, Addison-Wesley, 1997, ISBN: 0201896842.\n
- Strong requires closeness relative to \b both values being compared,
- Weak only requires only closeness relative to \b either \b one value.
- */
- FPC_STRONG, //!< "Very close" - Knuth equation 1 (the default).
- FPC_WEAK //!< "Close enough" - Knuth equation 2.
+{ // Two types of comparison.
+ FPC_STRONG, // "Very close" - Knuth equation 1' the default.
+ FPC_WEAK // "Close enough" - equation 2'.
+ // equations in Dougles E. Knuth, Seminumerical algorithms (3rd Ed) section 4.2.4, Vol II,
+ // pp 213-225, Addison-Wesley, 1997, ISBN: 0201896842.
+ // Strong requires closeness relative to BOTH values begin compared,
+ // Weak only requires only closeness to EITHER ONE value.
};
// GNU int gsl_fcmp (double x, double y, double epsilon) provides similar function.
@@ -55,28 +42,31 @@
// www.boost.org/libs/test/doc/components/test_tools/floating_point_comparison.html
// Comparison of Floating Point Numbers, Matthias Ruppwww.mrupp.info/Data/2007floatingcomp.pdf, July 2007.
// The pitfalls of verifying floating-point computations, David Monniaux
-// CNRS Ecole normale superieure, 1 Feb 2008, http://arxiv.org/abs/cs/0701192v4
+// CNRS Ecole normale sup´erieure, 1 Feb 2008, http://arxiv.org/abs/cs/0701192v4
// submitted to ACM TOPLAS.
-// \tparam FPT is Floating-Point Type: float, double, long double, or User-Defined like NTL quad_float or RR.
+// FPT is Floating-Point Type: float, double, long double, or User-Defined like NTL quad_float or RR.
// from boost/math/tools/precision.hpp
-template <class FPT> FPT max_value(FPT); //!< maximum value for floating-point type T.
-template <class FPT> FPT min_value(FPT); //!< minimum value for floating-point type T.
-template <class FPT> FPT epsilon(FPT); //!< epsilon for type T (about 1e-16 for double)
+template <class T> T max_value(T);
+template <class T> T min_value(T);
+template <class T> T epsilon(T);
template<typename FPT> FPT
-fpt_abs(FPT arg)
-{ //! abs function (just in case abs is not defined for a user-defined FPT).
+fpt_abs(FPT arg)
+{ // abs function (just in case abs is not defined for FPT).
return arg <static_cast<FPT>(0) ? -arg : arg;
}
template<typename FPT> FPT
safe_fpt_division(FPT f1, FPT f2)
-{ //! Division safe from underflow and overflow. (Both f1 and f2 must be unsigned here).
+{ // Safe from under and overflow.
+ // Both f1 and f2 must be unsigned here.
+
if( (f2 < static_cast<FPT>(1)) && (f1 > f2 * boost::math::tools::max_value<FPT>()) )
{ // Avoid overflow.
return boost::math::tools::max_value<FPT>();
}
+
if( (f1 == static_cast<FPT>(0))
|| ((f2 > static_cast<FPT>(1)) && (f1 < f2 * boost::math::tools::min_value<FPT>()) )
)
@@ -86,23 +76,17 @@
return f1 / f2;
} // safe_fpt_division(FPT f1, FPT f2)
-template<typename FPT = double> //! \tparam FPT floating-point type.
-class close_to
-{ /*!
- \class close_to
- \brief Test if two floating-point values are close within a chosen tolerance.
- \details Close can be one of two types of floating-point comparison "Very close" and "Close enough".
- equations in Dougles E. Knuth, Seminumerical algorithms (3rd Ed) section 4.2.4, Vol II,
- pp 213-225, Addison-Wesley, 1997, ISBN: 0201896842.
- Strong requires closeness relative to BOTH values begin compared,
- Weak only requires only closeness to EITHER ONE value.
+// Check two floating-point values are close within a chosen tolerance.
- */
+template<typename FPT = double>
+class close_to
+{
public:
- //! Constructor for close_to from tolerance and strength. (By design, percent is NOT implemented).
+
+ // One constructor for fraction tolerance only.
template<typename FPT>
- explicit close_to(FPT tolerance, //!< Fractional tolerance.
- floating_point_comparison_type fpc_type = FPC_STRONG) //!< strong requires closeness relative to both values.
+ explicit close_to(FPT tolerance,
+ floating_point_comparison_type fpc_type = FPC_STRONG)
:
fraction_tolerance_(tolerance),
strong_or_weak_(fpc_type)
@@ -112,91 +96,80 @@
BOOST_ASSERT(tolerance >= static_cast<FPT>(0));
}
+ //template<typename FPT>
close_to()
:
fraction_tolerance_(2 * boost::math::tools::epsilon<FPT>()),
strong_or_weak_(FPC_STRONG)
- { /*! Default is two epsilon for the FPT.\n
- Note that some user-defined floating-point types may not specialize std::numeric_limits<FPT>::epsilon()
- so it is convenient to use boost::math::tools::epsilon<FPT>(); instead.
- */
-
+ { // Default is two epsilon.
}
bool operator()(FPT left, FPT right) const
- { //! \brief Test if two floating-point values are close within a chosen tolerance.
- //! \details Tolerance can be interpreted as Knuth's "Very close" (equation 1), the default, or "Close enough" (equation 2).
-
+ {
FPT diff = fpt_abs(left - right);
FPT d1 = safe_fpt_division(diff, fpt_abs(right));
FPT d2 = safe_fpt_division(diff, fpt_abs(left));
- return strong_or_weak_
+ return strong_or_weak_
? ((d1 <= fraction_tolerance_) && (d2 <= fraction_tolerance_)) // Strong.
: ((d1 <= fraction_tolerance_) || (d2 <= fraction_tolerance_)); // Weak.
}
FPT size()
- { //! \return the chosen tolerance, as a \b fraction (not a percentage).
+ { // Get function.
return fraction_tolerance_;
}
floating_point_comparison_type strength()
- { //! \return strength of comparison, Knuth's "Very close" (equation 1), the default, or "Close enough" (equation 2).
+ { // Get function.
return strong_or_weak_;
}
private:
- FPT fraction_tolerance_; //!< tolerance as a fraction.
- floating_point_comparison_type strong_or_weak_; //!< Knuth's "Very close" (equation 1), the default, or "Close enough" (equation 2).
+ FPT fraction_tolerance_;
+ floating_point_comparison_type strong_or_weak_;
}; // class close_to
-template<typename FPT = double> //! \tparam FPT floating-point type.
-class smallest
-{ /*! \class smallest
- \brief Check floating-point value is smaller than a chosen small value,
- default is twice min_value() for the floating-point type FPT.
- \details
- It is somewhat common for beginners to add a comparison check to 0 before
- computing a division, in order to avoid possible division-by-zero exceptions or
- the generation of infinite results.\n
- A first objection to this practise is that, anyway,
- computing 1/x for x very close to zero will generate very large numbers
- that will most probably result in overflows later.\n
- Another objection, which few programmers know about and that we wish to draw attention
- to, is that it may actually fail to work, depending on what the compiler
- does, that is, the program may actually test that x == 0, then, further down,
- find that x = 0 without any apparent change to x!\n
- David Monniaux, http://arxiv.org/abs/cs/0701192v4.
- \tparam FPT A floating-point type, float, double, long double or user-defined like NTL quad_float or RR.
- */
+// Check floating-point value is smaller than a chosen small value.
+// David Monniaux, http://arxiv.org/abs/cs/0701192v4,
+// It is somewhat common for beginners to add a comparison check to 0 before
+// computing a division, in order to avoid possible division-by-zero exceptions or
+// the generation of infinite results. A first objection to this practise is that, anyway,
+// computing 1/x for x very close to zero will generate very large numbers
+// that will most probably result in overflows later.
+// Another objection, which few programmers know about and that we wish to draw attention
+// to, is that it may actually fail to work, depending on what the compiler
+// does that is, the program may actually test that x 6= 0, then, further down,
+// find that x = 0 without any apparent change to x!
+
+template<typename FPT = double>
+class smallest
+{
public:
template<typename FPT>
- explicit smallest(FPT s)
+ explicit smallest(FPT s)
:
smallest_(s)
- { /*! Constructor with user defined value of smallest, for example 10 * min_value<FPT>.
- Note that some user-defined floating-point types may not specialize std::numeric_limits<FPT>::min_value()
- so it is convenient to use boost::math::tools::min_value<FPT>(); instead.
- */
+ { // Constructor.
}
- smallest()
+ smallest()
:
smallest_(2 * boost::math::tools::min_value<FPT>())
- { /*! Default Constructor with smallest_ = 2. * boost::math::tools::min_value<double>();\n
- multiplier m = 2 (must be integer or static_cast<FPT>())
- is chosen to allow for a few bits of computation error.\n
- Pessimistic multiplier is the number of arithmetic operations,
- assuming every operation causes a 1 least significant bit error,
- but a more realistic average might be half this.
- */
+ { // Default Constructor.
+ // smallest_ = 2. * boost::math::tools::min_value<double>();
+ // multiplier m = 2 (must be integer or static_cast<FPT>())
+ // is chosen to allow for a few bits of computation error.
+ // Pessimistic multiplier is the number of arithmetic operations,
+ // assuming every operation causes a 1 least significant bit error,
+ // but a more realistic average would be half this.
}
+ template<typename FPT>
bool operator()(FPT fp_value, FPT s)
- { //! True if value is smaller than a smallest value s.
+ {
if (fpt_abs(fp_value) == static_cast<FPT>(0))
{ // Test for zero first in case FPT is actually an integer type zero,
// when the comparison < below would fail because
@@ -206,44 +179,37 @@
return fpt_abs(fp_value) < fpt_abs(s);
} // bool operator()
+ template<typename FPT>
bool operator()(FPT fp_value)
- { //! True if value is smaller than chosen smallest value.
+ {
+
if (fpt_abs(fp_value) == static_cast<FPT>(0))
{ // Test for zero first in case FPT is actually an integer type,
- // when the comparison < below would fail because smallest could become zero.
+ // when the comparison < below would fail because
+ // smallest could become zero.
return true;
}
return fpt_abs(fp_value) < fpt_abs(smallest_);
} // bool operator()
FPT size()
- { //! \return chosen smallest value that will be counted as effectively zero.
+ { // Get function.
return smallest_;
}
private:
- FPT smallest_; //!< Chosen smallest value that will be counted as effectively zero.
+ // Smallest value that will be counted as effectively zero.
+ FPT smallest_;
+
}; // class smallest
-// Define two convenience typedefs.
+// Since double and the default smallest value 2 * min_value = 4.45015e-308
+// is a very common requirement, provide an convenience alias for this:
+typedef smallest<double> tiny; // Allow tiny as a shorthand for 1e-308
-typedef smallest<double> tiny;
-/*!
- \typedef tiny
- \brief Allow tiny as a shorthand for twice the double min_value 4.45e-308.
- \details Since double and the default smallest value 2 * std::numeric_limits<double>::min_value() = 2 * 2.22507e-308 + 4.45015e-308
- is a very common requirement, provide an convenience alias for this.
-*/
-
-/*!
- \typedef neareq
- \brief Allow neareq as a shorthand for twice double epsilon = 4.44e-16
- \details Since double and the default close_to value 2 * epsilon = std::numeric_limits<double>::epsilon = 2 * 2.220446e-016 = 4.440892e-016
- is a very common requirement, provide an convenience alias for this.
-*/
-typedef close_to<double> neareq;
- // namespace math
- // namespace boost
+// Since double and the default smallest value 2 * min_value = 4.45015e-308
+// is a very common requirement, provide an convenience alias for this:
+typedef close_to<double> neareq; // Allow tiny as a shorthand for epsilon
#endif // BOOST_FLOATING_POINT_COMPARISON_HPP
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