lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [5006] Support infinities


From: Greg Chicares
Subject: [lmi-commits] [5006] Support infinities
Date: Tue, 22 Jun 2010 13:42:43 +0000

Revision: 5006
          http://svn.sv.gnu.org/viewvc/?view=rev&root=lmi&revision=5006
Author:   chicares
Date:     2010-06-22 13:42:42 +0000 (Tue, 22 Jun 2010)
Log Message:
-----------
Support infinities

Modified Paths:
--------------
    lmi/trunk/ieee754.hpp
    lmi/trunk/ieee754_test.cpp

Modified: lmi/trunk/ieee754.hpp
===================================================================
--- lmi/trunk/ieee754.hpp       2010-06-22 01:07:19 UTC (rev 5005)
+++ lmi/trunk/ieee754.hpp       2010-06-22 13:42:42 UTC (rev 5006)
@@ -35,8 +35,7 @@
 
 #include <limits>
 
-/// Quiet NaN on IEC559-conforming implementations; otherwise, an
-/// implausible value, optionally specified.
+/// Quiet NaN if available; else a slightly less implausible value.
 ///
 /// It is sometimes profitable to initialize a floating-point variable
 /// to a recognizably implausible value. A quiet NaN is generally the
@@ -74,5 +73,60 @@
 #endif // !defined __BORLANDC__
 }
 
+/// Return positive infinity.
+///
+/// Preconditions: T is a floating-point type that has an infinity.
+///
+/// Throws if any precondition is violated.
+///
+/// Rationale: std::numeric_limits<T>::infinity() silently returns
+/// zero if T has no infinity [18.2.1.5/1]; this function throws in
+/// that case to prevent surprises.
+///
+/// Static variables are volatile if initializing them might trigger a
+/// hardware exception.
+
+template<typename T>
+inline T infinity()
+{
+    BOOST_STATIC_ASSERT(::boost::is_float<T>::value);
+    BOOST_STATIC_ASSERT(std::numeric_limits<T>::has_infinity);
+    static T const volatile z = std::numeric_limits<T>::infinity();
+    return z;
+}
+
+/// Ascertain whether argument is infinite.
+///
+/// Preconditions: T is a floating-point type. (It need not have an
+/// infinity.)
+///
+/// Throws if any precondition is violated.
+///
+/// Eventually, the C++ standard library will provide std::isinf<T>(),
+/// which might replace this implementation when compilers support it.
+///
+/// Static variables are volatile if initializing them might trigger a
+/// hardware exception.
+///
+/// The present implementation compares the argument to positive and
+/// negative infinity, if infinity is available: it doesn't seem too
+/// outrageous to presume that infinity is negatable and that its
+/// positive and negative representations are unique. Alternatively,
+/// these conditions might be tested:
+///               std::numeric_limits<T>::max() < argument
+///   argument < -std::numeric_limits<T>::max()
+/// but it doesn't seem any safer to assume that would work better on
+/// a machine that doesn't conform to IEEE 754.
+
+template<typename T>
+inline bool is_infinite(T t)
+{
+    BOOST_STATIC_ASSERT(::boost::is_float<T>::value);
+    static T const volatile pos_inf =  std::numeric_limits<T>::infinity();
+    static T const volatile neg_inf = -std::numeric_limits<T>::infinity();
+    static bool const has_inf = std::numeric_limits<T>::has_infinity;
+    return has_inf && (pos_inf == t || neg_inf == t);
+}
+
 #endif // ieee754_hpp
 

Modified: lmi/trunk/ieee754_test.cpp
===================================================================
--- lmi/trunk/ieee754_test.cpp  2010-06-22 01:07:19 UTC (rev 5005)
+++ lmi/trunk/ieee754_test.cpp  2010-06-22 13:42:42 UTC (rev 5006)
@@ -1,4 +1,4 @@
-// IEEE 754 esoterica.
+// IEEE 754 esoterica--unit test.
 //
 // Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Gregory W. Chicares.
 //
@@ -34,6 +34,24 @@
 
 int test_main(int, char*[])
 {
+    BOOST_TEST(is_infinite(infinity<float      >()));
+    BOOST_TEST(is_infinite(infinity<double     >()));
+    BOOST_TEST(is_infinite(infinity<long double>()));
+
+    BOOST_TEST(is_infinite<float      >(-infinity<float      >()));
+    BOOST_TEST(is_infinite<float      >(-infinity<double     >()));
+    BOOST_TEST(is_infinite<float      >(-infinity<long double>()));
+    BOOST_TEST(is_infinite<double     >(-infinity<float      >()));
+    BOOST_TEST(is_infinite<double     >(-infinity<double     >()));
+    BOOST_TEST(is_infinite<double     >(-infinity<long double>()));
+    BOOST_TEST(is_infinite<long double>(-infinity<float      >()));
+    BOOST_TEST(is_infinite<long double>(-infinity<double     >()));
+    BOOST_TEST(is_infinite<long double>(-infinity<long double>()));
+
+    BOOST_TEST(!is_infinite(0.0));
+    BOOST_TEST(!is_infinite( std::numeric_limits<double>::max()));
+    BOOST_TEST(!is_infinite(-std::numeric_limits<double>::max()));
+
     if(std::numeric_limits<double>::has_quiet_NaN)
         {
         std::cerr << "has quiet NaN" << std::endl;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]