[pkg-boost-commits] r15019 - in /boost/trunk/debian: changelog patches/series patches/upstream-c99-annex-f-01.patch patches/upstream-c99-annex-f-02.patch patches/upstream-ilogb.patch

smr at users.alioth.debian.org smr at users.alioth.debian.org
Mon Dec 5 04:56:27 UTC 2016


Author: smr
Date: Mon Dec  5 04:56:27 2016
New Revision: 15019

URL: http://svn.debian.org/wsvn/pkg-boost/?sc=1&rev=15019
Log:
Fix ilogb / acos() issue.

Added:
    boost/trunk/debian/patches/upstream-c99-annex-f-01.patch
    boost/trunk/debian/patches/upstream-c99-annex-f-02.patch
    boost/trunk/debian/patches/upstream-ilogb.patch
Modified:
    boost/trunk/debian/changelog
    boost/trunk/debian/patches/series

Modified: boost/trunk/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-boost/boost/trunk/debian/changelog?rev=15019&op=diff
==============================================================================
--- boost/trunk/debian/changelog	(original)
+++ boost/trunk/debian/changelog	Mon Dec  5 04:56:27 2016
@@ -3,7 +3,12 @@
   * control: document fact that -doc package contains no docs.
     Closes: #844268.
 
- -- Steve M. Robbins <smr at debian.org>  Sun, 04 Dec 2016 22:49:48 -0600
+  * Upstream patches to fix ilogb issue.  Closes: #844495
+    - upstream-c99-annex-f-01.patch
+    - upstream-c99-annex-f-02.patch
+    - upstream-ilogb.patch
+
+ -- Steve M. Robbins <smr at debian.org>  Sun, 04 Dec 2016 22:56:05 -0600
 
 boost1.62 (1.62.0+dfsg-4) unstable; urgency=medium
 

Modified: boost/trunk/debian/patches/series
URL: http://svn.debian.org/wsvn/pkg-boost/boost/trunk/debian/patches/series?rev=15019&op=diff
==============================================================================
--- boost/trunk/debian/patches/series	(original)
+++ boost/trunk/debian/patches/series	Mon Dec  5 04:56:27 2016
@@ -1,3 +1,7 @@
+upstream-add-degree-reverse_graph.patch
+upstream-c99-annex-f-01.patch
+upstream-c99-annex-f-02.patch
+upstream-ilogb.patch
 chrono-duration.patch
 pythonid.patch
 fix-ftbfs-python-3.3.patch
@@ -5,6 +9,4 @@
 boost-python-examples.patch
 ppc64el-fp_traits-ibm-long-double.patch
 no-gcc-m-options.diff
-# fixed alternatively? boost-context-use-sysv-not-aapcs.patch
 no-gcc-march-options.patch
-upstream-add-degree-reverse_graph.patch

Added: boost/trunk/debian/patches/upstream-c99-annex-f-01.patch
URL: http://svn.debian.org/wsvn/pkg-boost/boost/trunk/debian/patches/upstream-c99-annex-f-01.patch?rev=15019&op=file
==============================================================================
--- boost/trunk/debian/patches/upstream-c99-annex-f-01.patch	(added)
+++ boost/trunk/debian/patches/upstream-c99-annex-f-01.patch	Mon Dec  5 04:56:27 2016
@@ -0,0 +1,2316 @@
+From 138a9055e2edc68dca2e78ff97ffe6276c17fa0a Mon Sep 17 00:00:00 2001
+From: jzmaddock <john at johnmaddock.co.uk>
+Date: Wed, 30 Nov 2016 19:00:55 +0000
+Subject: [PATCH] Big commit to bring things into line with C99 Annex F. See
+ https://svn.boost.org/trac/boost/ticket/12581.
+
+---
+ include/boost/multiprecision/cpp_bin_float.hpp     |   28 +-
+ .../cpp_bin_float/transcendental.hpp               |    1 +
+ include/boost/multiprecision/cpp_dec_float.hpp     |    7 +-
+ include/boost/multiprecision/debug_adaptor.hpp     |    9 +-
+ .../boost/multiprecision/detail/default_ops.hpp    |   94 +-
+ .../boost/multiprecision/detail/functions/pow.hpp  |  133 +-
+ .../boost/multiprecision/detail/functions/trig.hpp |   57 +-
+ include/boost/multiprecision/float128.hpp          |   20 +-
+ include/boost/multiprecision/logged_adaptor.hpp    |    7 +
+ include/boost/multiprecision/mpfr.hpp              |   23 +-
+ test/test_round.cpp                                |    9 +-
+ test/test_sf_import_c99.cpp                        | 1410 ++++++++++++++++++++
+ 12 files changed, 1713 insertions(+), 85 deletions(-)
+
+diff --git a/include/boost/multiprecision/cpp_bin_float.hpp b/include/boost/multiprecision/cpp_bin_float.hpp
+index 613c062..25d4329 100644
+--- a/include/boost/multiprecision/cpp_bin_float.hpp
++++ b/include/boost/multiprecision/cpp_bin_float.hpp
+@@ -1476,13 +1476,18 @@ inline void eval_sqrt(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE
+    using default_ops::eval_increment;
+    switch(arg.exponent())
+    {
+-   case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
+    case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
++      errno = EDOM;
++      // fallthrough...
++   case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
+       res = arg;
+       return;
+    case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
+       if(arg.sign())
++      {
+          res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
++         errno = EDOM;
++      }
+       else
+          res = arg;
+       return;
+@@ -1490,6 +1495,7 @@ inline void eval_sqrt(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE
+    if(arg.sign())
+    {
+       res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
++      errno = EDOM;
+       return;
+    }
+ 
+@@ -1518,8 +1524,10 @@ inline void eval_floor(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, Min
+    using default_ops::eval_increment;
+    switch(arg.exponent())
+    {
+-   case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
+    case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
++      errno = EDOM;
++      // fallthrough...
++   case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
+    case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
+       res = arg;
+       return;
+@@ -1559,9 +1567,11 @@ inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE
+    using default_ops::eval_increment;
+    switch(arg.exponent())
+    {
++   case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
++      errno = EDOM;
++      // fallthrough...
+    case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
+    case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
+-   case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
+       res = arg;
+       return;
+    }
+@@ -1596,6 +1606,12 @@ inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE
+ }
+ 
+ template<unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2>
++int eval_signbit(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val)
++{
++   return val.sign();
++}
++
++template<unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2>
+ inline std::size_t hash_value(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val)
+ {
+    std::size_t result = hash_value(val.bits());
+@@ -1620,12 +1636,6 @@ struct is_explicitly_convertible<FloatT, backends::cpp_bin_float<D2, B2, A2, E2,
+ #endif
+ 
+ template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+-inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& arg)
+-{
+-   return arg.backend().sign();
+-}
+-
+-template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>
+ copysign BOOST_PREVENT_MACRO_SUBSTITUTION(
+    const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& a,
+diff --git a/include/boost/multiprecision/cpp_bin_float/transcendental.hpp b/include/boost/multiprecision/cpp_bin_float/transcendental.hpp
+index 9037dd3..066bc45 100644
+--- a/include/boost/multiprecision/cpp_bin_float/transcendental.hpp
++++ b/include/boost/multiprecision/cpp_bin_float/transcendental.hpp
+@@ -70,6 +70,7 @@ void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>
+    if(type == (int)FP_NAN)
+    {
+       res = arg;
++      errno = EDOM;
+       return;
+    }
+    else if(type == (int)FP_INFINITE)
+diff --git a/include/boost/multiprecision/cpp_dec_float.hpp b/include/boost/multiprecision/cpp_dec_float.hpp
+index 9e0c290..bcda7cf 100644
+--- a/include/boost/multiprecision/cpp_dec_float.hpp
++++ b/include/boost/multiprecision/cpp_dec_float.hpp
+@@ -2847,12 +2847,7 @@ inline void eval_ceil(cpp_dec_float<Digits10, ExponentType, Allocator>& result,
+ template <unsigned Digits10, class ExponentType, class Allocator>
+ inline void eval_trunc(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x)
+ {
+-   if(!(x.isfinite)())
+-   {
+-      result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number<cpp_dec_float<Digits10, ExponentType, Allocator> >(x), number<cpp_dec_float<Digits10, ExponentType, Allocator> >(x), boost::math::policies::policy<>()).backend();
+-      return;
+-   }
+-   else if(x.isint())
++   if(x.isint() || !(x.isfinite)())
+    {
+       result = x;
+       return;
+diff --git a/include/boost/multiprecision/debug_adaptor.hpp b/include/boost/multiprecision/debug_adaptor.hpp
+index 1b69ba4..1e39503 100644
+--- a/include/boost/multiprecision/debug_adaptor.hpp
++++ b/include/boost/multiprecision/debug_adaptor.hpp
+@@ -282,6 +282,7 @@ inline void eval_ldexp(debug_adaptor<Backend>& result, const debug_adaptor<Backe
+ template <class Backend, class Exp>
+ inline void eval_scalbn(debug_adaptor<Backend>& result, const debug_adaptor<Backend>& arg, Exp exp)
+ {
++   using default_ops::eval_scalbn;
+    eval_scalbn(result.value(), arg.value(), exp);
+    result.update_view();
+ }
+@@ -289,6 +290,7 @@ inline void eval_scalbn(debug_adaptor<Backend>& result, const debug_adaptor<Back
+ template <class Backend>
+ inline typename Backend::exponent_type eval_ilogb(const debug_adaptor<Backend>& arg)
+ {
++   using default_ops::eval_ilogb;
+    return eval_ilogb(arg.value());
+ }
+ 
+@@ -456,12 +458,17 @@ NON_MEMBER_OP3(pow, "pow");
+ NON_MEMBER_OP3(atan2, "atan2");
+ 
+ template <class Backend>
++int eval_signbit(const debug_adaptor<Backend>& val)
++{
++   return eval_signbit(val.value());
++}
++
++template <class Backend>
+ std::size_t hash_value(const debug_adaptor<Backend>& val)
+ {
+    return hash_value(val.value());
+ }
+ 
+-
+ } // namespace backends
+ 
+ using backends::debug_adaptor;
+diff --git a/include/boost/multiprecision/detail/default_ops.hpp b/include/boost/multiprecision/detail/default_ops.hpp
+index 106ee1d..feab0aa 100644
+--- a/include/boost/multiprecision/detail/default_ops.hpp
++++ b/include/boost/multiprecision/detail/default_ops.hpp
+@@ -983,6 +983,25 @@ inline void eval_fmod(T& result, const T& a, const T& b)
+       result = temp;
+       return;
+    }
++   switch(eval_fpclassify(a))
++   {
++   case FP_ZERO:
++      result = a;
++      return;
++   case FP_INFINITE:
++   case FP_NAN:
++      result = std::numeric_limits<number<T> >::quiet_NaN().backend();
++      errno = EDOM;
++      return;
++   }
++   switch(eval_fpclassify(b))
++   {
++   case FP_ZERO:
++   case FP_NAN:
++      result = std::numeric_limits<number<T> >::quiet_NaN().backend();
++      errno = EDOM;
++      return;
++   }
+    T n;
+    eval_divide(result, a, b);
+    if(eval_get_sign(result) < 0)
+@@ -1162,10 +1181,14 @@ template <class T>
+ inline void eval_trunc(T& result, const T& a)
+ {
+    BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
+-   int c = eval_fpclassify(a);
+-   if(c == (int)FP_NAN || c == (int)FP_INFINITE)
++   switch(eval_fpclassify(a))
+    {
+-      result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number<T>(a), number<T>(a), boost::math::policies::policy<>()).backend();
++   case FP_NAN:
++      errno = EDOM;
++      // fallthrough...
++   case FP_ZERO:
++   case FP_INFINITE:
++      result = a;
+       return;
+    }
+    if(eval_get_sign(a) < 0)
+@@ -1212,12 +1235,17 @@ inline void eval_round(T& result, const T& a)
+    BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
+    typedef typename boost::multiprecision::detail::canonical<float, T>::type fp_type;
+    int c = eval_fpclassify(a);
+-   if((c == (int)FP_NAN) || (c == (int)FP_INFINITE))
++   if(c == (int)FP_NAN)
+    {
+-      result = boost::math::policies::raise_rounding_error("boost::multiprecision::round<%1%>(%1%)", 0, number<T>(a), number<T>(a), boost::math::policies::policy<>()).backend();
++      result = a;
++      errno = EDOM;
+       return;
+    }
+-   if(eval_get_sign(a) < 0)
++   if((c == FP_ZERO) || (c == (int)FP_INFINITE))
++   {
++      result = a;
++   }
++   else if(eval_get_sign(a) < 0)
+    {
+       eval_subtract(result, a, fp_type(0.5f));
+       eval_ceil(result, result);
+@@ -1450,19 +1478,48 @@ inline typename B::exponent_type eval_ilogb(const B& val)
+    switch(eval_fpclassify(val))
+    {
+    case FP_NAN:
+-      return (std::numeric_limits<typename B::exponent_type>::min)();
++#ifdef FP_ILOGBNAN
++      return FP_ILOGBNAN;
++#else
++      return (std::numeric_limits<typename B::exponent_type>::max)();
++#endif
+    case FP_INFINITE:
+       return (std::numeric_limits<typename B::exponent_type>::max)();
+    case FP_ZERO:
++#ifdef FP_ILOGB0
++      return FP_ILOGB0;
++#else
+       return (std::numeric_limits<typename B::exponent_type>::min)();
++#endif
+    }
+    B result;
+    eval_frexp(result, val, &e);
+    return e - 1;
+ }
++
++template <class T>
++int eval_signbit(const T& val);
++
+ template <class B>
+ inline void eval_logb(B& result, const B& val)
+ {
++   switch(eval_fpclassify(val))
++   {
++   case FP_NAN:
++      result = val;
++      errno = EDOM;
++      return;
++   case FP_ZERO:
++      result = std::numeric_limits<number<B> >::infinity().backend();
++      result.negate();
++      errno = ERANGE;
++      return;
++   case FP_INFINITE:
++      result = val;
++      if(eval_signbit(val))
++         result.negate();
++      return;
++   }
+    typedef typename boost::mpl::if_c<boost::is_same<boost::intmax_t, long>::value, boost::long_long_type, boost::intmax_t>::type max_t;
+    result = static_cast<max_t>(eval_ilogb(val));
+ }
+@@ -1600,6 +1657,12 @@ inline void eval_rint(R& result, const T& a)
+    eval_nearbyint(result, a);
+ }
+ 
++template <class T>
++inline int eval_signbit(const T& val)
++{
++   return eval_get_sign(val) < 0 ? 1 : 0;
++}
++
+ //
+ // These functions are implemented in separate files, but expanded inline here,
+ // DO NOT CHANGE THE ORDER OF THESE INCLUDES:
+@@ -1689,7 +1752,8 @@ inline int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::e
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+-   return arg.sign() < 0;
++   using default_ops::eval_signbit;
++   return eval_signbit(arg.backend());
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+@@ -1839,7 +1903,14 @@ namespace multiprecision{
+    template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+    inline multiprecision::number<Backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+    {
+-      return boost::math::lgamma(arg, c99_error_policy());
++      multiprecision::number<Backend, ExpressionTemplates> result;
++      result = boost::math::lgamma(arg, c99_error_policy());
++      if((boost::multiprecision::isnan)(result) && !(boost::multiprecision::isnan)(arg))
++      {
++         result = std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::infinity();
++         errno = ERANGE;
++      }
++      return result;
+    }
+    template <class tag, class A1, class A2, class A3, class A4>
+    inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+@@ -1850,6 +1921,11 @@ namespace multiprecision{
+    template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+    inline multiprecision::number<Backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+    {
++      if((arg == 0) && std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::has_infinity)
++      {
++         errno = ERANGE;
++         return 1 / arg;
++      }
+       return boost::math::tgamma(arg, c99_error_policy());
+    }
+    template <class tag, class A1, class A2, class A3, class A4>
+diff --git a/include/boost/multiprecision/detail/functions/pow.hpp b/include/boost/multiprecision/detail/functions/pow.hpp
+index b244a18..260f7c8 100644
+--- a/include/boost/multiprecision/detail/functions/pow.hpp
++++ b/include/boost/multiprecision/detail/functions/pow.hpp
+@@ -208,6 +208,7 @@ void eval_exp(T& result, const T& x)
+    if(type == (int)FP_NAN)
+    {
+       result = x;
++      errno = EDOM;
+       return;
+    }
+    else if(type == (int)FP_INFINITE)
+@@ -326,6 +327,29 @@ void eval_log(T& result, const T& arg)
+    typedef typename T::exponent_type exp_type;
+    typedef typename boost::multiprecision::detail::canonical<exp_type, T>::type canonical_exp_type;
+    typedef typename mpl::front<typename T::float_types>::type fp_type;
++   int s = eval_signbit(arg);
++   switch(eval_fpclassify(arg))
++   {
++   case FP_NAN:
++      result = arg;
++      errno = EDOM;
++      return;
++   case FP_INFINITE:
++      if(s) break;
++      result = arg;
++      return;
++   case FP_ZERO:
++      result = std::numeric_limits<number<T> >::has_infinity ? std::numeric_limits<number<T> >::infinity().backend() : (std::numeric_limits<number<T> >::max)().backend();
++      result.negate();
++      errno = ERANGE;
++      return;
++   }
++   if(s)
++   {
++      result = std::numeric_limits<number<T> >::quiet_NaN().backend();
++      errno = EDOM;
++      return;
++   }
+ 
+    exp_type e;
+    T t;
+@@ -427,19 +451,21 @@ inline void eval_pow(T& result, const T& x, const T& a)
+       return;
+    }
+ 
+-   if(a.compare(si_type(1)) == 0)
++   if((a.compare(si_type(1)) == 0) || (x.compare(si_type(1)) == 0))
+    {
+       result = x;
+       return;
+    }
++   if(a.compare(si_type(0)) == 0)
++   {
++      result = si_type(1);
++      return;
++   }
+ 
+    int type = eval_fpclassify(x);
+ 
+    switch(type)
+    {
+-   case FP_INFINITE:
+-      result = x;
+-      return;
+    case FP_ZERO:
+       switch(eval_fpclassify(a))
+       {
+@@ -449,13 +475,41 @@ inline void eval_pow(T& result, const T& x, const T& a)
+       case FP_NAN:
+          result = a;
+          break;
++      case FP_NORMAL:
++      {
++         // Need to check for a an odd integer as a special case:
++         try 
++         {
++            boost::intmax_t i;
++            eval_convert_to(&i, a);
++            if((a.compare(i) == 0) && (i & 1) && eval_signbit(a))
++            {
++               result = std::numeric_limits<number<T> >::infinity().backend();
++               if(eval_signbit(x))
++                  result.negate();
++               errno = ERANGE;
++               return;
++            }
++         }
++         catch(const std::exception&)
++         {
++            // fallthrough..
++         }
++      }
+       default:
+-         result = x;
++         if(eval_signbit(a))
++         {
++            result = std::numeric_limits<number<T> >::infinity().backend();
++            errno = ERANGE;
++         }
++         else
++            result = x;
+          break;
+       }
+       return;
+    case FP_NAN:
+       result = x;
++      errno = ERANGE;
+       return;
+    default: ;
+    }
+@@ -478,6 +532,16 @@ inline void eval_pow(T& result, const T& x, const T& a)
+    }
+    
+    typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type an;
++   typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type max_an =
++      std::numeric_limits<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>::is_specialized ?
++      (std::numeric_limits<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>::max)() :
++      static_cast<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>(1) << (sizeof(typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type) * CHAR_BIT - 2);
++   typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type min_an = 
++      std::numeric_limits<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>::is_specialized ?
++      (std::numeric_limits<typename boost::multiprecision::detail::canonical<boost::intmax_t, T>::type>::min)() :
++      -min_an;
++
++
+    T fa;
+ #ifndef BOOST_NO_EXCEPTIONS
+    try
+@@ -521,8 +585,33 @@ inline void eval_pow(T& result, const T& x, const T& a)
+          // conversion failed, just fall through, value is not an integer.
+       }
+ #endif
+-      if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
++      eval_floor(result, a);
++      // -1^INF is a special case in C99:
++      if((x.compare(si_type(-1)) == 0) && (eval_fpclassify(a) == FP_INFINITE))
++      {
++         result = si_type(1);
++      }
++      else if(a.compare(result) == 0)
++      {
++         // exponent is so large we have no fractional part:
++         if(x.compare(si_type(-1)) < 0)
++         {
++            result = std::numeric_limits<number<T, et_on> >::infinity().backend();
++         }
++         else
++         {
++            result = si_type(0);
++         }
++      }
++      else if(type == FP_INFINITE)
++      {
++         result = std::numeric_limits<number<T, et_on> >::infinity().backend();
++      }
++      else if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
++      {
+          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
++         errno = EDOM;
++      }
+       else
+       {
+          BOOST_THROW_EXCEPTION(std::domain_error("Result of pow is undefined or non-real and there is no NaN for this number type."));
+@@ -534,7 +623,7 @@ inline void eval_pow(T& result, const T& x, const T& a)
+ 
+    eval_subtract(da, a, an);
+ 
+-   if((x.compare(fp_type(0.5)) >= 0) && (x.compare(fp_type(0.9)) < 0))
++   if((x.compare(fp_type(0.5)) >= 0) && (x.compare(fp_type(0.9)) < 0) && (an < max_an) && (an > min_an))
+    {
+       if(a.compare(fp_type(1e-5f)) <= 0)
+       {
+@@ -618,14 +707,20 @@ void eval_exp2(T& result, const T& arg)
+    // Check for pure-integer arguments which can be either signed or unsigned.
+    typename boost::multiprecision::detail::canonical<typename T::exponent_type, T>::type i;
+    T temp;
+-   eval_trunc(temp, arg);
+-   eval_convert_to(&i, temp);
+-   if(arg.compare(i) == 0)
+-   {
+-      temp = static_cast<typename mpl::front<typename T::unsigned_types>::type>(1u);
+-      eval_ldexp(result, temp, i);
+-      return;
++   try {
++      eval_trunc(temp, arg);
++      eval_convert_to(&i, temp);
++      if(arg.compare(i) == 0)
++      {
++         temp = static_cast<typename mpl::front<typename T::unsigned_types>::type>(1u);
++         eval_ldexp(result, temp, i);
++         return;
++      }
+    }
++   catch(const boost::math::rounding_error&)
++   { /* Fallthrough */ }
++   catch(const std::runtime_error&)
++   { /* Fallthrough */ }
+ 
+    temp = static_cast<typename mpl::front<typename T::unsigned_types>::type>(2u);
+    eval_pow(result, temp, arg);
+@@ -669,6 +764,8 @@ namespace detail{
+       switch(eval_fpclassify(x))
+       {
+       case FP_NAN:
++         errno = EDOM;
++         // fallthrough...
+       case FP_INFINITE:
+          if(p_sinh)
+             *p_sinh = x;
+@@ -742,6 +839,14 @@ inline void eval_tanh(T& result, const T& x)
+    BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The tanh function is only valid for floating point types.");
+   T c;
+   detail::sinhcosh(x, &result, &c);
++  if((eval_fpclassify(result) == FP_INFINITE) && (eval_fpclassify(c) == FP_INFINITE))
++  {
++     bool s = eval_signbit(result) != eval_signbit(c);
++     result = static_cast<typename mpl::front<typename T::unsigned_types>::type>(1u);
++     if(s)
++        result.negate();
++     return;
++  }
+   eval_divide(result, c);
+ }
+ 
+diff --git a/include/boost/multiprecision/detail/functions/trig.hpp b/include/boost/multiprecision/detail/functions/trig.hpp
+index c84a639..75835df 100644
+--- a/include/boost/multiprecision/detail/functions/trig.hpp
++++ b/include/boost/multiprecision/detail/functions/trig.hpp
+@@ -91,12 +91,15 @@ void eval_sin(T& result, const T& x)
+    case FP_INFINITE:
+    case FP_NAN:
+       if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
++      {
+          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
++         errno = EDOM;
++      }
+       else
+          BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+       return;
+    case FP_ZERO:
+-      result = ui_type(0);
++      result = x;
+       return;
+    default: ;
+    }
+@@ -238,7 +241,10 @@ void eval_cos(T& result, const T& x)
+    case FP_INFINITE:
+    case FP_NAN:
+       if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
++      {
+          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
++         errno = EDOM;
++      }
+       else
+          BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+       return;
+@@ -422,12 +428,15 @@ void eval_asin(T& result, const T& x)
+    case FP_NAN:
+    case FP_INFINITE:
+       if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
++      {
+          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
++         errno = EDOM;
++      }
+       else
+          BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+       return;
+    case FP_ZERO:
+-      result = ui_type(0);
++      result = x;
+       return;
+    default: ;
+    }
+@@ -442,7 +451,10 @@ void eval_asin(T& result, const T& x)
+    if(c > 0)
+    {
+       if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
++      {
+          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
++         errno = EDOM;
++      }
+       else
+          BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+       return;
+@@ -535,7 +547,10 @@ inline void eval_acos(T& result, const T& x)
+    case FP_NAN:
+    case FP_INFINITE:
+       if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
++      {
+          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
++         errno = EDOM;
++      }
+       else
+          BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+       return;
+@@ -551,7 +566,10 @@ inline void eval_acos(T& result, const T& x)
+    if(c > 0)
+    {
+       if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
++      {
+          result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
++         errno = EDOM;
++      }
+       else
+          BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
+       return;
+@@ -584,9 +602,10 @@ void eval_atan(T& result, const T& x)
+    {
+    case FP_NAN:
+       result = x;
++      errno = EDOM;
+       return;
+    case FP_ZERO:
+-      result = ui_type(0);
++      result = x;
+       return;
+    case FP_INFINITE:
+       if(eval_get_sign(x) < 0)
+@@ -694,24 +713,41 @@ void eval_atan2(T& result, const T& y, const T& x)
+    {
+    case FP_NAN:
+       result = y;
++      errno = EDOM;
+       return;
+    case FP_ZERO:
+       {
+-         int c = eval_get_sign(x);
+-         if(c < 0)
++         if(eval_signbit(x))
++         {
+             result = get_constant_pi<T>();
+-         else if(c >= 0)
+-            result = ui_type(0); // Note we allow atan2(0,0) to be zero, even though it's mathematically undefined
++            if(eval_signbit(y))
++               result.negate();
++         }
++         else
++         {
++            result = y; // Note we allow atan2(0,0) to be +-zero, even though it's mathematically undefined
++         }
+          return;
+       }
+    case FP_INFINITE:
+       {
+          if(eval_fpclassify(x) == FP_INFINITE)
+          {
+-            if(std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
+-               result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
++            if(eval_signbit(x))
++            {
++               // 3Pi/4
++               eval_ldexp(result, get_constant_pi<T>(), -2);
++               eval_subtract(result, get_constant_pi<T>());
++               if(eval_get_sign(y) >= 0)
++                  result.negate();
++            }
+             else
+-               BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
++            {
++               // Pi/4
++               eval_ldexp(result, get_constant_pi<T>(), -2);
++               if(eval_get_sign(y) < 0)
++                  result.negate();
++            }
+          }
+          else
+          {
+@@ -727,6 +763,7 @@ void eval_atan2(T& result, const T& y, const T& x)
+    {
+    case FP_NAN:
+       result = x;
++      errno = EDOM;
+       return;
+    case FP_ZERO:
+       {
+diff --git a/include/boost/multiprecision/float128.hpp b/include/boost/multiprecision/float128.hpp
+index 702d488..8de3af6 100644
+--- a/include/boost/multiprecision/float128.hpp
++++ b/include/boost/multiprecision/float128.hpp
+@@ -399,15 +399,6 @@ inline void eval_fabs(float128_backend& result, const float128_backend& arg)
+ 
+ inline void eval_trunc(float128_backend& result, const float128_backend& arg)
+ {
+-   if(isnanq(arg.value()) || isinfq(arg.value()))
+-   {
+-      result = boost::math::policies::raise_rounding_error(
+-            "boost::multiprecision::trunc<%1%>(%1%)", 0, 
+-            number<float128_backend, et_off>(arg), 
+-            number<float128_backend, et_off>(arg), 
+-            boost::math::policies::policy<>()).backend();
+-      return;
+-   }
+    result.value() = truncq(arg.value());
+ }
+ /*
+@@ -494,6 +485,11 @@ inline void eval_multiply_add(float128_backend& result, const float128_backend&
+    result.value() = fmaq(a.value(), b.value(), c.value());
+ }
+ 
++inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const float128_backend& arg)
++{
++   return ::signbitq(arg.value());
++}
++
+ inline std::size_t hash_value(const float128_backend& val)
+ {
+    return  boost::hash_value(static_cast<double>(val.value()));
+@@ -553,12 +549,6 @@ inline std::size_t hash_value(const float128_backend& val)
+    }
+ 
+    template <multiprecision::expression_template_option ExpressionTemplates>
+-   inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& arg)
+-   {
+-      return ::signbitq(arg.backend().value());
+-   }
+-
+-   template <multiprecision::expression_template_option ExpressionTemplates>
+    inline boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& b)
+    {
+       return ::copysignq(a.backend().value(), b.backend().value());
+diff --git a/include/boost/multiprecision/logged_adaptor.hpp b/include/boost/multiprecision/logged_adaptor.hpp
+index 2f916dd..7cb33ee 100644
+--- a/include/boost/multiprecision/logged_adaptor.hpp
++++ b/include/boost/multiprecision/logged_adaptor.hpp
+@@ -507,6 +507,13 @@ NON_MEMBER_OP3(pow, "pow");
+ NON_MEMBER_OP3(atan2, "atan2");
+ 
+ template <class Backend>
++int eval_signbit(const logged_adaptor<Backend>& val)
++{
++   using default_ops::eval_signbit;
++   return eval_signbit(val.value());
++}
++
++template <class Backend>
+ std::size_t hash_value(const logged_adaptor<Backend>& val)
+ {
+    return hash_value(val.value());
+diff --git a/include/boost/multiprecision/mpfr.hpp b/include/boost/multiprecision/mpfr.hpp
+index 440517f..c78771c 100644
+--- a/include/boost/multiprecision/mpfr.hpp
++++ b/include/boost/multiprecision/mpfr.hpp
+@@ -1286,11 +1286,6 @@ inline void eval_floor(mpfr_float_backend<Digits10, AllocateType>& result, const
+ template <unsigned Digits10, mpfr_allocation_type AllocateType>
+ inline void eval_trunc(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
+ {
+-   if(0 == mpfr_number_p(val.data()))
+-   {
+-      result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number<mpfr_float_backend<Digits10, AllocateType> >(val), number<mpfr_float_backend<Digits10, AllocateType> >(val), boost::math::policies::policy<>()).backend();
+-      return;
+-   }
+    mpfr_trunc(result.data(), val.data());
+ }
+ template <unsigned Digits10, mpfr_allocation_type AllocateType>
+@@ -1505,6 +1500,12 @@ inline void eval_multiply_subtract(mpfr_float_backend<Digits10, AllocateType>& r
+ }
+ 
+ template <unsigned Digits10, mpfr_allocation_type AllocateType>
++inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const mpfr_float_backend<Digits10, AllocateType>& arg)
++{
++   return (arg.data()[0]._mpfr_sign < 0) ? 1 : 0;
++}
++
++template <unsigned Digits10, mpfr_allocation_type AllocateType>
+ inline std::size_t hash_value(const mpfr_float_backend<Digits10, AllocateType>& val)
+ {
+    std::size_t result = 0;
+@@ -1546,24 +1547,12 @@ typedef number<mpfr_float_backend<50, allocate_stack> >    static_mpfr_float_50;
+ typedef number<mpfr_float_backend<100, allocate_stack> >   static_mpfr_float_100;
+ 
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
+-inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+-{
+-   return (arg.backend().data()[0]._mpfr_sign < 0) ? 1 : 0;
+-}
+-
+-template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& b)
+ {
+    return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(-a) : a;
+ }
+ 
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
+-inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
+-{
+-   return (arg.backend().value().data()[0]._mpfr_sign < 0) ? 1 : 0;
+-}
+-
+-template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& b)
+ {
+    return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>(-a) : a;
+diff --git a/test/test_round.cpp b/test/test_round.cpp
+index a1b3935..a810316 100644
+--- a/test/test_round.cpp
++++ b/test/test_round.cpp
+@@ -340,7 +340,7 @@ void test()
+ #endif
+    if(std::numeric_limits<T>::has_infinity)
+    {
+-      BOOST_CHECK_THROW(static_cast<T>(round(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
++      BOOST_CHECK_EQUAL(static_cast<T>(round(std::numeric_limits<T>::infinity())), std::numeric_limits<T>::infinity()); // See C99 Annex F.
+       BOOST_CHECK_THROW(static_cast<T>(iround(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+       BOOST_CHECK_THROW(static_cast<T>(iround(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+       BOOST_CHECK_THROW(static_cast<T>(lround(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+@@ -352,7 +352,7 @@ void test()
+    }
+    if(std::numeric_limits<T>::has_quiet_NaN)
+    {
+-      BOOST_CHECK_THROW(static_cast<T>(round(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
++      BOOST_CHECK((boost::multiprecision::isnan)(round(std::numeric_limits<T>::quiet_NaN())));
+       BOOST_CHECK_THROW(static_cast<T>(iround(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
+       BOOST_CHECK_THROW(static_cast<T>(lround(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
+    #ifdef BOOST_HAS_LONG_LONG
+@@ -369,7 +369,8 @@ void test()
+ #endif
+    if(std::numeric_limits<T>::has_infinity)
+    {
+-      BOOST_CHECK_THROW(static_cast<T>(trunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
++      BOOST_CHECK_EQUAL(static_cast<T>(trunc(std::numeric_limits<T>::infinity())), std::numeric_limits<T>::infinity());
++      BOOST_CHECK_EQUAL(static_cast<T>(trunc(-std::numeric_limits<T>::infinity())), -std::numeric_limits<T>::infinity());
+       BOOST_CHECK_THROW(static_cast<T>(itrunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+       BOOST_CHECK_THROW(static_cast<T>(itrunc(-std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+       BOOST_CHECK_THROW(static_cast<T>(ltrunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error);
+@@ -381,7 +382,7 @@ void test()
+    }
+    if(std::numeric_limits<T>::has_quiet_NaN)
+    {
+-      BOOST_CHECK_THROW(static_cast<T>(trunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
++      BOOST_CHECK((boost::multiprecision::isnan)(trunc(std::numeric_limits<T>::quiet_NaN())));
+       BOOST_CHECK_THROW(static_cast<T>(itrunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
+       BOOST_CHECK_THROW(static_cast<T>(ltrunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error);
+    #ifdef BOOST_HAS_LONG_LONG
+diff --git a/test/test_sf_import_c99.cpp b/test/test_sf_import_c99.cpp
+index 3d088a1..42133e7 100644
+--- a/test/test_sf_import_c99.cpp
++++ b/test/test_sf_import_c99.cpp
+@@ -40,11 +40,13 @@
+ #endif
+ #ifdef TEST_CPP_BIN_FLOAT
+ #include <boost/multiprecision/cpp_bin_float.hpp>
++#include <boost/multiprecision/debug_adaptor.hpp>
+ #endif
+ #ifdef TEST_FLOAT128
+ #include <boost/multiprecision/float128.hpp>
+ #endif
+ 
++#include <boost/math/constants/constants.hpp>
+ #include "test.hpp"
+ 
+ #ifdef signbit
+@@ -583,6 +585,1412 @@ void test_poison()
+ #endif
+ }
+ 
++template <class T>
++typename boost::enable_if_c<std::numeric_limits<T>::is_specialized>::type check_invalid(const T& val)
++{
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      BOOST_CHECK(isnan(val));
++   }
++   else
++   {
++      BOOST_CHECK_EQUAL(val, 0);
++   }
++   BOOST_CHECK_EQUAL(errno, EDOM);
++   errno = 0;
++}
++
++template <class T>
++typename boost::disable_if_c<std::numeric_limits<T>::is_specialized>::type check_invalid(const T& val)
++{
++   check_invalid(static_cast<typename T::result_type>(val));
++}
++
++void check_erange()
++{
++   BOOST_CHECK_EQUAL(errno, ERANGE);
++   errno = 0;
++}
++
++template <class T>
++void test_c99_appendix_F()
++{
++   //
++   // Tests conformance to non-normative appendix F.9.1 of C99, basically how to handle
++   // special cases, infinities and NaN's.
++   //
++   errno = 0;
++   // F.9.1.1:
++   T arg = 1;
++   T val = acos(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = 2;
++   check_invalid(acos(arg));
++   arg = -2;
++   check_invalid(acos(arg));
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      check_invalid(acos(arg));
++      arg = -std::numeric_limits<T>::infinity();
++      check_invalid(acos(arg));
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(acos(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(acos(arg));
++   }
++   // F.9.1.2:
++   arg = 0;
++   val = asin(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = asin(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   arg = 2;
++   check_invalid(asin(arg));
++   arg = -2;
++   check_invalid(asin(arg));
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      check_invalid(asin(arg));
++      arg = -std::numeric_limits<T>::infinity();
++      check_invalid(asin(arg));
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(asin(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(asin(arg));
++   }
++   // F.9.1.3:
++   arg = 0;
++   val = atan(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = atan(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = atan(arg);
++      BOOST_CHECK_EQUAL(val, boost::math::constants::half_pi<T>());
++      arg = -std::numeric_limits<T>::infinity();
++      val = atan(arg);
++      BOOST_CHECK_EQUAL(val, -boost::math::constants::half_pi<T>());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(asin(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(asin(arg));
++   }
++   // F.9.1.4:
++   arg = 0;
++   T arg2 = 0;
++   val = atan2(arg, arg2);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   arg2 = -arg2;
++   if(signbit(arg2))
++   {
++      arg = 0;
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, boost::math::constants::pi<T>());
++      BOOST_CHECK(signbit(val) == 0);
++      arg = -arg;
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, -boost::math::constants::pi<T>());
++      BOOST_CHECK(signbit(val));
++   }
++   arg = 0;
++   arg2 = -2;
++   val = atan2(arg, arg2);
++   BOOST_CHECK_EQUAL(val, boost::math::constants::pi<T>());
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, -boost::math::constants::pi<T>());
++   }
++   arg = 0;
++   arg2 = 2;
++   val = atan2(arg, arg2);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   arg = -2;
++   arg2 = 0;
++   val = atan2(arg, arg2);
++   BOOST_CHECK_EQUAL(val, -boost::math::constants::half_pi<T>());
++   arg2 = -arg2;
++   if(signbit(arg2))
++   {
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, -boost::math::constants::half_pi<T>());
++   }
++   arg = 2;
++   arg2 = 0;
++   val = atan2(arg, arg2);
++   BOOST_CHECK_EQUAL(val, boost::math::constants::half_pi<T>());
++   arg2 = -arg2;
++   if(signbit(arg2))
++   {
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, boost::math::constants::half_pi<T>());
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = 2;
++      arg2 = -std::numeric_limits<T>::infinity();
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, boost::math::constants::pi<T>());
++      arg = -arg;
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, -boost::math::constants::pi<T>());
++      arg = 2;
++      arg2 = std::numeric_limits<T>::infinity();
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++      arg = -arg;
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++      arg = std::numeric_limits<T>::infinity();
++      arg2 = 2;
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, boost::math::constants::half_pi<T>());
++      arg = -arg;
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, -boost::math::constants::half_pi<T>());
++      arg = std::numeric_limits<T>::infinity();
++      arg2 = -2;
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, boost::math::constants::half_pi<T>());
++      arg = -arg;
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, -boost::math::constants::half_pi<T>());
++      arg = std::numeric_limits<T>::infinity();
++      arg2 = -std::numeric_limits<T>::infinity();
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, boost::math::constants::three_quarters_pi<T>());
++      arg = -arg;
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, -boost::math::constants::three_quarters_pi<T>());
++      arg = std::numeric_limits<T>::infinity();
++      arg2 = std::numeric_limits<T>::infinity();
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, ldexp(boost::math::constants::pi<T>(), -2));
++      arg = -arg;
++      val = atan2(arg, arg2);
++      BOOST_CHECK_EQUAL(val, -ldexp(boost::math::constants::pi<T>(), -2));
++      if(std::numeric_limits<T>::has_quiet_NaN)
++      {
++         arg = std::numeric_limits<T>::quiet_NaN();
++         arg2 = 2;
++         check_invalid(atan2(arg, arg2));
++         std::swap(arg, arg2);
++         check_invalid(atan2(arg, arg2));
++         arg = std::numeric_limits<T>::quiet_NaN();
++         check_invalid(atan2(arg, arg2));
++      }
++   }
++   // F.9.1.5:
++   arg = 0;
++   val = cos(arg);
++   BOOST_CHECK_EQUAL(val, 1);
++   arg = -arg;
++   BOOST_CHECK_EQUAL(val, 1);
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      check_invalid(cos(arg));
++      arg = -std::numeric_limits<T>::infinity();
++      check_invalid(cos(arg));
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(cos(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(cos(arg));
++   }
++   // F.9.1.6:
++   arg = 0;
++   val = sin(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = sin(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      check_invalid(sin(arg));
++      arg = -std::numeric_limits<T>::infinity();
++      check_invalid(sin(arg));
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(sin(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(sin(arg));
++   }
++   // F.9.1.7:
++   arg = 0;
++   val = tan(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = tan(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      check_invalid(tan(arg));
++      arg = -std::numeric_limits<T>::infinity();
++      check_invalid(tan(arg));
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(tan(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(tan(arg));
++   }
++   // F.9.2.1:
++   arg = 1;
++   val = acosh(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   check_invalid(acosh(arg));
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = acosh(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++
++      arg = -std::numeric_limits<T>::infinity();
++      check_invalid(acosh(arg));
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(acosh(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(acosh(arg));
++   }
++   // F.9.2.2:
++   arg = 0;
++   val = asinh(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = asinh(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = asinh(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++
++      arg = -std::numeric_limits<T>::infinity();
++      val = asinh(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(asinh(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(asinh(arg));
++   }
++   // F.9.2.3:
++   arg = 0;
++   val = atanh(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = atanh(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   arg = 2;
++   check_invalid(atanh(arg));
++   arg = -3;
++   check_invalid(atanh(arg));
++
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = 1;
++      val = atanh(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      BOOST_CHECK(signbit(val) == 0);
++      check_erange();
++      arg = -arg;
++      val = atanh(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++      BOOST_CHECK(signbit(val));
++      check_erange();
++
++      arg = std::numeric_limits<T>::infinity();
++      check_invalid(atanh(arg));
++      arg = -std::numeric_limits<T>::infinity();
++      check_invalid(atanh(arg));
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(atanh(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(atanh(arg));
++   }
++   // F.9.2.4:
++   arg = 0;
++   val = cosh(arg);
++   BOOST_CHECK_EQUAL(val, 1);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = cosh(arg);
++      BOOST_CHECK_EQUAL(val, 1);
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = (std::numeric_limits<T>::max)();
++      val = cosh(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = cosh(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = std::numeric_limits<T>::infinity();
++      val = cosh(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = cosh(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(cosh(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(cosh(arg));
++   }
++   // F.9.2.5:
++   arg = 0;
++   val = sinh(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = sinh(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = (std::numeric_limits<T>::max)();
++      val = sinh(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = sinh(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++      arg = std::numeric_limits<T>::infinity();
++      val = sinh(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = sinh(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(sinh(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(sinh(arg));
++   }
++   // F.9.2.6:
++   arg = 0;
++   val = tanh(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = tanh(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   arg = (std::numeric_limits<T>::max)();
++   val = tanh(arg);
++   BOOST_CHECK_EQUAL(val, 1);
++   arg = -arg;
++   val = tanh(arg);
++   BOOST_CHECK_EQUAL(val, -1);
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = tanh(arg);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg = -arg;
++      val = tanh(arg);
++      BOOST_CHECK_EQUAL(val, -1);
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(tanh(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(tanh(arg));
++   }
++   // F.9.3.1:
++   arg = 0;
++   val = exp(arg);
++   BOOST_CHECK_EQUAL(val, 1);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = exp(arg);
++      BOOST_CHECK_EQUAL(val, 1);
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = exp(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = exp(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++      arg = (std::numeric_limits<T>::max)();
++      val = exp(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = exp(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(exp(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(exp(arg));
++   }
++   // F.9.3.2:
++   arg = 0;
++   val = exp2(arg);
++   BOOST_CHECK_EQUAL(val, 1);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = exp2(arg);
++      BOOST_CHECK_EQUAL(val, 1);
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = exp2(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = exp2(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++      arg = (std::numeric_limits<T>::max)();
++      val = exp2(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = exp2(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(exp2(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(exp2(arg));
++   }
++   // F.9.3.3:
++   arg = 0;
++   val = expm1(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = expm1(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = expm1(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = expm1(arg);
++      BOOST_CHECK_EQUAL(val, -1);
++      arg = (std::numeric_limits<T>::max)();
++      val = expm1(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = expm1(arg);
++      BOOST_CHECK_EQUAL(val, -1);
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(expm1(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(expm1(arg));
++   }
++   // F.9.3.4:
++   arg = 0;
++   int ival;
++   val = frexp(arg, &ival);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK_EQUAL(ival, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = frexp(arg, &ival);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = frexp(arg, &ival);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = frexp(arg, &ival);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      val = frexp(arg, &ival);
++      BOOST_CHECK(isnan(val));
++   }
++   // F.9.3.5:
++   int fp_ilogb0 =
++#ifdef FP_ILOGB0
++      FP_ILOGB0;
++#else
++      INT_MIN;
++#endif
++   int fp_ilogbnan = 
++#ifdef FP_ILOGBNAN
++      FP_ILOGBNAN;
++#else
++      INT_MAX;
++#endif
++
++   arg = 0;
++   ival = ilogb(arg);
++   BOOST_CHECK_EQUAL(ival, fp_ilogb0);
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      ival = ilogb(arg);
++      BOOST_CHECK_EQUAL(ival, INT_MAX);
++      arg = -arg;
++      ival = ilogb(arg);
++      BOOST_CHECK_EQUAL(ival, INT_MAX);
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      ival = ilogb(arg);
++      BOOST_CHECK_EQUAL(ival, fp_ilogbnan);
++   }
++   // F.9.3.7:
++   arg = 1;
++   val = log(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = 0;
++      val = log(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++      check_erange();
++      arg = -arg;
++      if(signbit(arg))
++      {
++         val = log(arg);
++         BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++         check_erange();
++      }
++      arg = -1;
++      check_invalid(log(arg));
++      arg = -std::numeric_limits<T>::infinity();
++      check_invalid(log(arg));
++      arg = std::numeric_limits<T>::infinity();
++      val = log(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(log(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(log(arg));
++   }
++   // F.9.3.8:
++   arg = 1;
++   val = log10(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = 0;
++      val = log10(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++      check_erange();
++      arg = -arg;
++      if(signbit(arg))
++      {
++         val = log10(arg);
++         BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++         check_erange();
++      }
++      arg = -1;
++      check_invalid(log10(arg));
++      arg = -std::numeric_limits<T>::infinity();
++      check_invalid(log10(arg));
++      arg = std::numeric_limits<T>::infinity();
++      val = log10(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(log10(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(log10(arg));
++   }
++   // F.9.3.9:
++   arg = 0;
++   val = log1p(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = log1p(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = -1;
++      val = log1p(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++      check_erange();
++      arg = -2;
++      check_invalid(log1p(arg));
++      arg = -std::numeric_limits<T>::infinity();
++      check_invalid(log1p(arg));
++      arg = std::numeric_limits<T>::infinity();
++      val = log1p(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(log1p(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(log1p(arg));
++   }
++   // F.9.3.10:
++   arg = 1;
++   val = log2(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = 0;
++      val = log2(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++      check_erange();
++      arg = -arg;
++      if(signbit(arg))
++      {
++         val = log2(arg);
++         BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++         check_erange();
++      }
++      arg = -1;
++      check_invalid(log2(arg));
++      arg = -std::numeric_limits<T>::infinity();
++      check_invalid(log2(arg));
++      arg = std::numeric_limits<T>::infinity();
++      val = log2(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(log2(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(log2(arg));
++   }
++   // F.9.3.11:
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = 0;
++      val = logb(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++      check_erange();
++      arg = -arg;
++      if(signbit(arg))
++      {
++         val = logb(arg);
++         BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++         check_erange();
++      }
++      arg = std::numeric_limits<T>::infinity();
++      val = logb(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -std::numeric_limits<T>::infinity();
++      val = logb(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(logb(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(logb(arg));
++   }
++   // F.9.3.13:
++   arg = 0;
++   val = scalbn(arg, 2);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = scalbn(arg, 2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = scalbn(arg, -100);
++      BOOST_CHECK_EQUAL(val, arg);
++      arg = -arg;
++      val = scalbn(arg, -100);
++      BOOST_CHECK_EQUAL(val, arg);
++   }
++   // F.9.4.1:
++   arg = 0;
++   val = cbrt(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = cbrt(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = cbrt(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -std::numeric_limits<T>::infinity();
++      val = cbrt(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(cbrt(arg));
++      arg = -std::numeric_limits<T>::quiet_NaN();
++      check_invalid(cbrt(arg));
++   }
++   // F.9.4.2:
++   arg = 0;
++   val = fabs(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = fabs(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = fabs(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -std::numeric_limits<T>::infinity();
++      val = fabs(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   }
++   // F.9.4.3:
++   arg = 2;
++   arg2 = 0;
++   val = hypot(arg, arg2);
++   BOOST_CHECK_EQUAL(val, arg);
++   arg2 = -arg2;
++   val = hypot(arg, arg2);
++   BOOST_CHECK_EQUAL(val, arg);
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      arg2 = 2;
++      val = hypot(arg, arg2);
++      BOOST_CHECK_EQUAL(val, arg);
++      arg = -arg;
++      val = hypot(arg, arg2);
++      BOOST_CHECK_EQUAL(val, -arg);
++      arg2 = std::numeric_limits<T>::quiet_NaN();
++      val = hypot(arg, arg2);
++      BOOST_CHECK_EQUAL(val, -arg);
++      arg = -arg;
++      val = hypot(arg, arg2);
++      BOOST_CHECK_EQUAL(val, arg);
++   }
++   // F.9.4.4:
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = 0;
++      arg2 = -3;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      check_erange();
++      arg = -arg;
++      if(signbit(arg))
++      {
++         val = pow(arg, arg2);
++         BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++         check_erange();
++      }
++      arg = 0;
++      arg2 = -2;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      check_erange();
++      arg = -arg;
++      if(signbit(arg))
++      {
++         val = pow(arg, arg2);
++         BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++         check_erange();
++      }
++      arg = 0;
++      arg2 = 3;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++      arg = -arg;
++      if(signbit(arg))
++      {
++         val = pow(arg, arg2);
++         BOOST_CHECK_EQUAL(val, 0);
++         BOOST_CHECK(signbit(val));
++      }
++      arg = 0;
++      arg2 = 2;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++      arg = -arg;
++      if(signbit(arg))
++      {
++         val = pow(arg, arg2);
++         BOOST_CHECK_EQUAL(val, 0);
++         BOOST_CHECK(signbit(val));
++      }
++      arg = -1;
++      arg2 = std::numeric_limits<T>::infinity();
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg2 = -std::numeric_limits<T>::infinity();
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg = 1;
++      arg2 = 0;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg2 = std::numeric_limits<T>::infinity();
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg2 = -std::numeric_limits<T>::infinity();
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg2 = std::numeric_limits<T>::quiet_NaN();
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg = 0;
++      arg2 = 0;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg2 = -arg2;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg = std::numeric_limits<T>::infinity();
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg2 = -arg2;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg = std::numeric_limits<T>::quiet_NaN();
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg2 = -arg2;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 1);
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = -2.5;
++      arg2 = 2.5;
++      check_invalid(pow(arg, arg2));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = 0.5;
++      arg2 = -std::numeric_limits<T>::infinity();
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -0.25;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = 2.5;
++      arg2 = -std::numeric_limits<T>::infinity();
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      arg = -arg;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      arg = 2.5;
++      arg2 = std::numeric_limits<T>::infinity();
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -std::numeric_limits<T>::infinity();
++      arg2 = -3;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++      arg2 = -2;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++      arg2 = -2.5;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++      arg2 = 3;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++      arg2 = 2;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg2 = 2.5;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg; // +INF
++      arg2 = -2;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++      arg2 = -3;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++      arg2 = -3.5;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++      arg2 = 2;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg2 = 3;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg2 = 3.5;
++      val = pow(arg, arg2);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   }
++   // F.9.4.5:
++   arg = 0;
++   val = sqrt(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = sqrt(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = sqrt(arg);
++      BOOST_CHECK_EQUAL(val, arg);
++      arg = -arg;
++      check_invalid(sqrt(arg));
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(sqrt(arg));
++   }
++   // F.9.5.1:
++   arg = 0;
++   val = erf(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = erf(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = erf(arg);
++      BOOST_CHECK_EQUAL(val, 1);
++      arg = -arg;
++      val = erf(arg);
++      BOOST_CHECK_EQUAL(val, -1);
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(erf(arg));
++   }
++   // F.9.5.2:
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = erfc(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val) == 0);
++      arg = -arg;
++      val = erfc(arg);
++      BOOST_CHECK_EQUAL(val, 2);
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(erfc(arg));
++   }
++   // F.9.5.3:
++   arg = 1;
++   val = lgamma(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = 2;
++   val = lgamma(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = 0;
++   val = lgamma(arg);
++   BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   check_erange();
++   arg = -1;
++   val = lgamma(arg);
++   BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   check_erange();
++   arg = -2;
++   val = lgamma(arg);
++   BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   check_erange();
++   arg = -std::numeric_limits<T>::infinity();
++   val = lgamma(arg);
++   BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   arg = std::numeric_limits<T>::infinity();
++   val = lgamma(arg);
++   BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(lgamma(arg));
++   }
++   // F.9.5.4:
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = 0;
++      val = tgamma(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      check_erange();
++      arg = -arg;
++      if(signbit(arg))
++      {
++         val = tgamma(arg);
++         BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++         check_erange();
++      }
++      arg = -1;
++      check_invalid(tgamma(arg));
++      arg = -std::numeric_limits<T>::infinity();
++      check_invalid(tgamma(arg));
++      arg = std::numeric_limits<T>::infinity();
++      val = tgamma(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(tgamma(arg));
++   }
++   // F.9.6.1:
++   arg = 0;
++   val = ceil(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = ceil(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = ceil(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = ceil(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(ceil(arg));
++   }
++   // F.9.6.2:
++   arg = 0;
++   val = floor(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = floor(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = floor(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = floor(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(floor(arg));
++   }
++   // F.9.6.3:
++   arg = 0;
++   val = nearbyint(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = nearbyint(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = nearbyint(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = nearbyint(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(nearbyint(arg));
++   }
++   // F.9.6.4:
++   arg = 0;
++   val = rint(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = rint(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = rint(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = rint(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(rint(arg));
++   }
++   // F.9.6.6:
++   arg = 0;
++   val = round(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = round(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = round(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = round(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(round(arg));
++   }
++   // F.9.6.8:
++   arg = 0;
++   val = trunc(arg);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = trunc(arg);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      val = trunc(arg);
++      BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
++      arg = -arg;
++      val = trunc(arg);
++      BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      check_invalid(trunc(arg));
++   }
++   // F.9.7.1:
++   arg = 0;
++   arg2 = 2;
++   val = fmod(arg, arg2);
++   BOOST_CHECK_EQUAL(val, 0);
++   BOOST_CHECK(signbit(val) == 0);
++   arg = -arg;
++   if(signbit(arg))
++   {
++      val = fmod(arg, arg2);
++      BOOST_CHECK_EQUAL(val, 0);
++      BOOST_CHECK(signbit(val));
++   }
++   if(std::numeric_limits<T>::has_infinity)
++   {
++      arg = std::numeric_limits<T>::infinity();
++      check_invalid(fmod(arg, arg2));
++      arg = -arg;
++      check_invalid(fmod(arg, arg2));
++      arg = 2;
++      arg2 = 0;
++      check_invalid(fmod(arg, arg2));
++      check_invalid(fmod(arg, -arg2));
++   }
++   if(std::numeric_limits<T>::has_quiet_NaN)
++   {
++      arg = std::numeric_limits<T>::quiet_NaN();
++      arg2 = 2;
++      check_invalid(fmod(arg, arg2));
++      swap(arg, arg2);
++      check_invalid(fmod(arg, arg2));
++      check_invalid(fmod(arg2, arg2));
++   }
++}
++
+ int main()
+ {
+    test_poison<float>();
+@@ -617,6 +2025,8 @@ int main()
+ #ifdef TEST_CPP_BIN_FLOAT
+    test<boost::multiprecision::cpp_bin_float_50>();
+    test<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<100>, boost::multiprecision::et_on> >();
++   test_c99_appendix_F<boost::multiprecision::cpp_bin_float_50>();
++   test_c99_appendix_F<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<100>, boost::multiprecision::et_on> >();
+ #endif
+ #ifdef TEST_FLOAT128
+    test<boost::multiprecision::float128>();

Added: boost/trunk/debian/patches/upstream-c99-annex-f-02.patch
URL: http://svn.debian.org/wsvn/pkg-boost/boost/trunk/debian/patches/upstream-c99-annex-f-02.patch?rev=15019&op=file
==============================================================================
--- boost/trunk/debian/patches/upstream-c99-annex-f-02.patch	(added)
+++ boost/trunk/debian/patches/upstream-c99-annex-f-02.patch	Mon Dec  5 04:56:27 2016
@@ -0,0 +1,501 @@
+From 26ceb6ef386f5fb879ddccca59cc3bdc57c124f3 Mon Sep 17 00:00:00 2001
+From: jzmaddock <john at johnmaddock.co.uk>
+Date: Fri, 2 Dec 2016 17:54:36 +0000
+Subject: [PATCH] Get cpp_dec_float, float128, and mpfr passing the C99 annex F
+ tests. See https://svn.boost.org/trac/boost/ticket/12581.
+
+---
+ include/boost/multiprecision/cpp_dec_float.hpp     | 38 ++++++++-
+ .../boost/multiprecision/detail/functions/pow.hpp  | 41 ++++++++--
+ include/boost/multiprecision/mpfr.hpp              |  7 +-
+ test/test_sf_import_c99.cpp                        | 94 ++++++++++++++--------
+ 4 files changed, 138 insertions(+), 42 deletions(-)
+
+diff --git a/include/boost/multiprecision/cpp_dec_float.hpp b/include/boost/multiprecision/cpp_dec_float.hpp
+index bcda7cf..17bb276 100644
+--- a/include/boost/multiprecision/cpp_dec_float.hpp
++++ b/include/boost/multiprecision/cpp_dec_float.hpp
+@@ -1254,9 +1254,15 @@ cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, Expone
+ {
+    // Compute the square root of *this.
+ 
++   if((isinf)() && !isneg())
++   {
++      return *this;
++   }
++
+    if(isneg() || (!(isfinite)()))
+    {
+       *this = nan();
++      errno = EDOM;
+       return *this;
+    }
+ 
+@@ -2312,6 +2318,11 @@ void cpp_dec_float<Digits10, ExponentType, Allocator>::from_unsigned_long_long(c
+    fpclass = cpp_dec_float_finite;
+    prec_elem = cpp_dec_float_elem_number;
+ 
++   if(u == 0)
++   {
++      return;
++   }
++
+    std::size_t i =static_cast<std::size_t>(0u);
+ 
+    boost::ulong_long_type uu = u;
+@@ -2822,6 +2833,8 @@ inline void eval_floor(cpp_dec_float<Digits10, ExponentType, Allocator>& result,
+    result = x;
+    if(!(x.isfinite)() || x.isint())
+    {
++      if((x.isnan)())
++         errno = EDOM;
+       return;
+    }
+ 
+@@ -2836,6 +2849,8 @@ inline void eval_ceil(cpp_dec_float<Digits10, ExponentType, Allocator>& result,
+    result = x;
+    if(!(x.isfinite)() || x.isint())
+    {
++      if((x.isnan)())
++         errno = EDOM;
+       return;
+    }
+ 
+@@ -2850,6 +2865,8 @@ inline void eval_trunc(cpp_dec_float<Digits10, ExponentType, Allocator>& result,
+    if(x.isint() || !(x.isfinite)())
+    {
+       result = x;
++      if((x.isnan)())
++         errno = EDOM;
+       return;
+    }
+    result = x.extract_integer_part();
+@@ -2858,6 +2875,20 @@ inline void eval_trunc(cpp_dec_float<Digits10, ExponentType, Allocator>& result,
+ template <unsigned Digits10, class ExponentType, class Allocator>
+ inline ExponentType eval_ilogb(const cpp_dec_float<Digits10, ExponentType, Allocator>& val)
+ {
++   if(val.iszero())
++#ifdef FP_ILOGB0
++      return  FP_ILOGB0;
++#else
++      return INT_MIN;
++#endif
++   if((val.isinf)())
++      return INT_MAX;
++   if((val.isnan)())
++#ifdef FP_ILOGBNAN
++      return FP_ILOGBNAN;
++#else
++      return INT_MAX;
++#endif
+    // Set result, to the exponent of val:
+    return val.order();
+ }
+@@ -2892,15 +2923,16 @@ template <unsigned Digits10, class ExponentType, class Allocator>
+ inline void eval_frexp(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x, ExponentType* e)
+ {
+    result = x;
+-   if(result.isneg())
+-      result.negate();
+ 
+-   if(result.iszero())
++   if(result.iszero() || (result.isinf)() || (result.isnan)())
+    {
+       *e = 0;
+       return;
+    }
+ 
++   if(result.isneg())
++      result.negate();
++
+    ExponentType t = result.order();
+    BOOST_MP_USING_ABS
+    if(abs(t) < ((std::numeric_limits<ExponentType>::max)() / 1000))
+diff --git a/include/boost/multiprecision/detail/functions/pow.hpp b/include/boost/multiprecision/detail/functions/pow.hpp
+index 260f7c8..514a9aa 100644
+--- a/include/boost/multiprecision/detail/functions/pow.hpp
++++ b/include/boost/multiprecision/detail/functions/pow.hpp
+@@ -213,7 +213,6 @@ void eval_exp(T& result, const T& x)
+    }
+    else if(type == (int)FP_INFINITE)
+    {
+-      result = x;
+       if(isneg)
+          result = ui_type(0u);
+       else 
+@@ -278,6 +277,17 @@ void eval_exp(T& result, const T& x)
+       detail::pow_imp(result, get_constant_e<T>(), ll, mpl::true_());
+       return;
+    }
++   else if(exp_series.compare(x) == 0)
++   {
++      // We have a value that has no fractional part, but is too large to fit 
++      // in a long long, in this situation the code below will fail, so
++      // we're just going to assume that this will overflow:
++      if(isneg)
++         result = ui_type(0);
++      else
++         result = std::numeric_limits<number<T> >::has_infinity ? std::numeric_limits<number<T> >::infinity().backend() : (std::numeric_limits<number<T> >::max)().backend();
++      return;
++   }
+ 
+    // The algorithm for exp has been taken from MPFUN.
+    // exp(t) = [ (1 + r + r^2/2! + r^3/3! + r^4/4! ...)^p2 ] * 2^n
+@@ -482,12 +492,29 @@ inline void eval_pow(T& result, const T& x, const T& a)
+          {
+             boost::intmax_t i;
+             eval_convert_to(&i, a);
+-            if((a.compare(i) == 0) && (i & 1) && eval_signbit(a))
++            if(a.compare(i) == 0)
+             {
+-               result = std::numeric_limits<number<T> >::infinity().backend();
+-               if(eval_signbit(x))
+-                  result.negate();
+-               errno = ERANGE;
++               if(eval_signbit(a))
++               {
++                  if(i & 1)
++                  {
++                     result = std::numeric_limits<number<T> >::infinity().backend();
++                     if(eval_signbit(x))
++                        result.negate();
++                     errno = ERANGE;
++                  }
++                  else
++                  {
++                     result = std::numeric_limits<number<T> >::infinity().backend();
++                     errno = ERANGE;
++                  }
++               }
++               else if(i & 1)
++               {
++                  result = x;
++               }
++               else
++                  result = si_type(0);
+                return;
+             }
+          }
+@@ -792,6 +819,8 @@ namespace detail{
+          T e_px, e_mx;
+          eval_exp(e_px, x);
+          eval_divide(e_mx, ui_type(1), e_px);
++         if(eval_signbit(e_mx) != eval_signbit(e_px))
++            e_mx.negate();  // Handles lack of signed zero in some types
+ 
+          if(p_sinh) 
+          { 
+diff --git a/include/boost/multiprecision/mpfr.hpp b/include/boost/multiprecision/mpfr.hpp
+index c78771c..f6f9a62 100644
+--- a/include/boost/multiprecision/mpfr.hpp
++++ b/include/boost/multiprecision/mpfr.hpp
+@@ -1322,7 +1322,12 @@ inline int eval_fpclassify(const mpfr_float_backend<Digits10, AllocateType>& val
+ template <unsigned Digits10, mpfr_allocation_type AllocateType>
+ inline void eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const mpfr_float_backend<Digits10, AllocateType>& e)
+ {
+-   mpfr_pow(result.data(), b.data(), e.data(), GMP_RNDN);
++   if(mpfr_zero_p(b.data()) && mpfr_integer_p(e.data()) && (mpfr_signbit(e.data()) == 0) && mpfr_fits_ulong_p(e.data(), GMP_RNDN) && (mpfr_get_ui(e.data(), GMP_RNDN) & 1))
++   {
++      mpfr_set(result.data(), b.data(), GMP_RNDN);
++   }
++   else
++      mpfr_pow(result.data(), b.data(), e.data(), GMP_RNDN);
+ }
+ 
+ #ifdef BOOST_MSVC
+diff --git a/test/test_sf_import_c99.cpp b/test/test_sf_import_c99.cpp
+index 42133e7..8ddb901 100644
+--- a/test/test_sf_import_c99.cpp
++++ b/test/test_sf_import_c99.cpp
+@@ -586,6 +586,25 @@ void test_poison()
+ }
+ 
+ template <class T>
++bool type_sets_errno(const T&)
++{
++   return true;
++}
++#ifdef TEST_MPFR_50
++template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
++bool type_sets_errno(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> &)
++{
++   return false;
++}
++#endif
++#ifdef TEST_FLOAT128
++bool type_sets_errno(const boost::multiprecision::float128 &)
++{
++   return false;
++}
++#endif
++
++template <class T>
+ typename boost::enable_if_c<std::numeric_limits<T>::is_specialized>::type check_invalid(const T& val)
+ {
+    if(std::numeric_limits<T>::has_quiet_NaN)
+@@ -596,7 +615,8 @@ typename boost::enable_if_c<std::numeric_limits<T>::is_specialized>::type check_
+    {
+       BOOST_CHECK_EQUAL(val, 0);
+    }
+-   BOOST_CHECK_EQUAL(errno, EDOM);
++   if(type_sets_errno(val))
++      BOOST_CHECK_EQUAL(errno, EDOM);
+    errno = 0;
+ }
+ 
+@@ -606,9 +626,11 @@ typename boost::disable_if_c<std::numeric_limits<T>::is_specialized>::type check
+    check_invalid(static_cast<typename T::result_type>(val));
+ }
+ 
+-void check_erange()
++template <class T>
++void check_erange(const T& val)
+ {
+-   BOOST_CHECK_EQUAL(errno, ERANGE);
++   if(type_sets_errno(val))
++      BOOST_CHECK_EQUAL(errno, ERANGE);
+    errno = 0;
+ }
+ 
+@@ -620,6 +642,7 @@ void test_c99_appendix_F()
+    // special cases, infinities and NaN's.
+    //
+    errno = 0;
++   T tol = std::numeric_limits<T>::epsilon();
+    // F.9.1.1:
+    T arg = 1;
+    T val = acos(arg);
+@@ -783,9 +806,12 @@ void test_c99_appendix_F()
+       BOOST_CHECK_EQUAL(val, 0);
+       BOOST_CHECK(signbit(val) == 0);
+       arg = -arg;
+-      val = atan2(arg, arg2);
+-      BOOST_CHECK_EQUAL(val, 0);
+-      BOOST_CHECK(signbit(val));
++      if(signbit(-T(0)))
++      {
++         val = atan2(arg, arg2);
++         BOOST_CHECK_EQUAL(val, 0);
++         BOOST_CHECK(signbit(val));
++      }
+       arg = std::numeric_limits<T>::infinity();
+       arg2 = 2;
+       val = atan2(arg, arg2);
+@@ -803,17 +829,17 @@ void test_c99_appendix_F()
+       arg = std::numeric_limits<T>::infinity();
+       arg2 = -std::numeric_limits<T>::infinity();
+       val = atan2(arg, arg2);
+-      BOOST_CHECK_EQUAL(val, boost::math::constants::three_quarters_pi<T>());
++      BOOST_CHECK_CLOSE_FRACTION(val, boost::math::constants::three_quarters_pi<T>(), tol);
+       arg = -arg;
+       val = atan2(arg, arg2);
+-      BOOST_CHECK_EQUAL(val, -boost::math::constants::three_quarters_pi<T>());
++      BOOST_CHECK_CLOSE_FRACTION(val, -boost::math::constants::three_quarters_pi<T>(), tol);
+       arg = std::numeric_limits<T>::infinity();
+       arg2 = std::numeric_limits<T>::infinity();
+       val = atan2(arg, arg2);
+-      BOOST_CHECK_EQUAL(val, ldexp(boost::math::constants::pi<T>(), -2));
++      BOOST_CHECK_CLOSE_FRACTION(val, ldexp(boost::math::constants::pi<T>(), -2), tol);
+       arg = -arg;
+       val = atan2(arg, arg2);
+-      BOOST_CHECK_EQUAL(val, -ldexp(boost::math::constants::pi<T>(), -2));
++      BOOST_CHECK_CLOSE_FRACTION(val, -ldexp(boost::math::constants::pi<T>(), -2), tol);
+       if(std::numeric_limits<T>::has_quiet_NaN)
+       {
+          arg = std::numeric_limits<T>::quiet_NaN();
+@@ -972,12 +998,12 @@ void test_c99_appendix_F()
+       val = atanh(arg);
+       BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
+       BOOST_CHECK(signbit(val) == 0);
+-      check_erange();
++      check_erange(val);
+       arg = -arg;
+       val = atanh(arg);
+       BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
+       BOOST_CHECK(signbit(val));
+-      check_erange();
++      check_erange(val);
+ 
+       arg = std::numeric_limits<T>::infinity();
+       check_invalid(atanh(arg));
+@@ -1265,13 +1291,13 @@ void test_c99_appendix_F()
+       arg = 0;
+       val = log(arg);
+       BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
+-      check_erange();
++      check_erange(val);
+       arg = -arg;
+       if(signbit(arg))
+       {
+          val = log(arg);
+          BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
+-         check_erange();
++         check_erange(val);
+       }
+       arg = -1;
+       check_invalid(log(arg));
+@@ -1298,13 +1324,13 @@ void test_c99_appendix_F()
+       arg = 0;
+       val = log10(arg);
+       BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
+-      check_erange();
++      check_erange(val);
+       arg = -arg;
+       if(signbit(arg))
+       {
+          val = log10(arg);
+          BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
+-         check_erange();
++         check_erange(val);
+       }
+       arg = -1;
+       check_invalid(log10(arg));
+@@ -1338,7 +1364,7 @@ void test_c99_appendix_F()
+       arg = -1;
+       val = log1p(arg);
+       BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
+-      check_erange();
++      check_erange(val);
+       arg = -2;
+       check_invalid(log1p(arg));
+       arg = -std::numeric_limits<T>::infinity();
+@@ -1364,13 +1390,13 @@ void test_c99_appendix_F()
+       arg = 0;
+       val = log2(arg);
+       BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
+-      check_erange();
++      check_erange(val);
+       arg = -arg;
+       if(signbit(arg))
+       {
+          val = log2(arg);
+          BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
+-         check_erange();
++         check_erange(val);
+       }
+       arg = -1;
+       check_invalid(log2(arg));
+@@ -1393,13 +1419,13 @@ void test_c99_appendix_F()
+       arg = 0;
+       val = logb(arg);
+       BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
+-      check_erange();
++      check_erange(val);
+       arg = -arg;
+       if(signbit(arg))
+       {
+          val = logb(arg);
+          BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
+-         check_erange();
++         check_erange(val);
+       }
+       arg = std::numeric_limits<T>::infinity();
+       val = logb(arg);
+@@ -1516,25 +1542,25 @@ void test_c99_appendix_F()
+       arg2 = -3;
+       val = pow(arg, arg2);
+       BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
+-      check_erange();
++      check_erange(val);
+       arg = -arg;
+       if(signbit(arg))
+       {
+          val = pow(arg, arg2);
+          BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
+-         check_erange();
++         check_erange(val);
+       }
+       arg = 0;
+       arg2 = -2;
+       val = pow(arg, arg2);
+       BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
+-      check_erange();
++      check_erange(val);
+       arg = -arg;
+       if(signbit(arg))
+       {
+          val = pow(arg, arg2);
+          BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
+-         check_erange();
++         check_erange(val);
+       }
+       arg = 0;
+       arg2 = 3;
+@@ -1558,7 +1584,7 @@ void test_c99_appendix_F()
+       {
+          val = pow(arg, arg2);
+          BOOST_CHECK_EQUAL(val, 0);
+-         BOOST_CHECK(signbit(val));
++         BOOST_CHECK(signbit(val) == 0);
+       }
+       arg = -1;
+       arg2 = std::numeric_limits<T>::infinity();
+@@ -1633,7 +1659,8 @@ void test_c99_appendix_F()
+       arg2 = -3;
+       val = pow(arg, arg2);
+       BOOST_CHECK_EQUAL(val, 0);
+-      BOOST_CHECK(signbit(val));
++      if(signbit(-T(0)))
++         BOOST_CHECK(signbit(val));
+       arg2 = -2;
+       val = pow(arg, arg2);
+       BOOST_CHECK_EQUAL(val, 0);
+@@ -1753,15 +1780,15 @@ void test_c99_appendix_F()
+    arg = 0;
+    val = lgamma(arg);
+    BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
+-   check_erange();
++   check_erange(val);
+    arg = -1;
+    val = lgamma(arg);
+    BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
+-   check_erange();
++   check_erange(val);
+    arg = -2;
+    val = lgamma(arg);
+    BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
+-   check_erange();
++   check_erange(val);
+    arg = -std::numeric_limits<T>::infinity();
+    val = lgamma(arg);
+    BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
+@@ -1779,13 +1806,13 @@ void test_c99_appendix_F()
+       arg = 0;
+       val = tgamma(arg);
+       BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
+-      check_erange();
++      check_erange(val);
+       arg = -arg;
+       if(signbit(arg))
+       {
+          val = tgamma(arg);
+          BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
+-         check_erange();
++         check_erange(val);
+       }
+       arg = -1;
+       check_invalid(tgamma(arg));
+@@ -2002,6 +2029,7 @@ int main()
+ #ifdef TEST_MPFR_50
+    test<boost::multiprecision::mpfr_float_50>();
+    test<boost::multiprecision::mpfr_float_100>();
++   test_c99_appendix_F<boost::multiprecision::mpfr_float_50>();
+ #endif
+ #ifdef TEST_MPFI_50
+    test<boost::multiprecision::mpfi_float_50>();
+@@ -2010,6 +2038,7 @@ int main()
+ #ifdef TEST_CPP_DEC_FLOAT
+    test<boost::multiprecision::cpp_dec_float_50>();
+    test<boost::multiprecision::cpp_dec_float_100>();
++   test_c99_appendix_F<boost::multiprecision::cpp_dec_float_50>();
+ #ifndef SLOW_COMPLER
+    // Some "peculiar" digit counts which stress our code:
+    test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<65> > >();
+@@ -2030,6 +2059,7 @@ int main()
+ #endif
+ #ifdef TEST_FLOAT128
+    test<boost::multiprecision::float128>();
++   test_c99_appendix_F<boost::multiprecision::float128>();
+ #endif
+ 
+    return boost::report_errors();

Added: boost/trunk/debian/patches/upstream-ilogb.patch
URL: http://svn.debian.org/wsvn/pkg-boost/boost/trunk/debian/patches/upstream-ilogb.patch?rev=15019&op=file
==============================================================================
--- boost/trunk/debian/patches/upstream-ilogb.patch	(added)
+++ boost/trunk/debian/patches/upstream-ilogb.patch	Mon Dec  5 04:56:27 2016
@@ -0,0 +1,96 @@
+From c0df5b6747d09268256b59501c3cab746112268e Mon Sep 17 00:00:00 2001
+From: jzmaddock <john at johnmaddock.co.uk>
+Date: Sat, 3 Dec 2016 08:50:38 +0000
+Subject: [PATCH] Change ilogb to consistently return the minimum value of the
+ exponent type (which may be either narrower or wider than the int return type
+ specified in C99). Change transcendental code which uses ilogb for loop
+ termination, to check for a minimal value return to correctly handle the case
+ that the value has gone to zero. See
+ https://svn.boost.org/trac/boost/ticket/12625
+
+---
+ include/boost/multiprecision/cpp_dec_float.hpp         | 6 +-----
+ include/boost/multiprecision/detail/default_ops.hpp    | 4 ----
+ include/boost/multiprecision/detail/functions/trig.hpp | 8 ++------
+ test/test_sf_import_c99.cpp                            | 7 +------
+ 4 files changed, 4 insertions(+), 21 deletions(-)
+
+diff --git a/include/boost/multiprecision/cpp_dec_float.hpp b/include/boost/multiprecision/cpp_dec_float.hpp
+index 17bb276..f9e6a22 100644
+--- a/include/boost/multiprecision/cpp_dec_float.hpp
++++ b/include/boost/multiprecision/cpp_dec_float.hpp
+@@ -2876,11 +2876,7 @@ template <unsigned Digits10, class ExponentType, class Allocator>
+ inline ExponentType eval_ilogb(const cpp_dec_float<Digits10, ExponentType, Allocator>& val)
+ {
+    if(val.iszero())
+-#ifdef FP_ILOGB0
+-      return  FP_ILOGB0;
+-#else
+-      return INT_MIN;
+-#endif
++      return (std::numeric_limits<ExponentType>::min)();
+    if((val.isinf)())
+       return INT_MAX;
+    if((val.isnan)())
+diff --git a/include/boost/multiprecision/detail/default_ops.hpp b/include/boost/multiprecision/detail/default_ops.hpp
+index feab0aa..334db06 100644
+--- a/include/boost/multiprecision/detail/default_ops.hpp
++++ b/include/boost/multiprecision/detail/default_ops.hpp
+@@ -1486,11 +1486,7 @@ inline typename B::exponent_type eval_ilogb(const B& val)
+    case FP_INFINITE:
+       return (std::numeric_limits<typename B::exponent_type>::max)();
+    case FP_ZERO:
+-#ifdef FP_ILOGB0
+-      return FP_ILOGB0;
+-#else
+       return (std::numeric_limits<typename B::exponent_type>::min)();
+-#endif
+    }
+    B result;
+    eval_frexp(result, val, &e);
+diff --git a/include/boost/multiprecision/detail/functions/trig.hpp b/include/boost/multiprecision/detail/functions/trig.hpp
+index 75835df..319b708 100644
+--- a/include/boost/multiprecision/detail/functions/trig.hpp
++++ b/include/boost/multiprecision/detail/functions/trig.hpp
+@@ -527,10 +527,8 @@ void eval_asin(T& result, const T& x)
+       eval_divide(sine, cosine);
+       eval_subtract(result, sine);
+       current_precision = eval_ilogb(sine);
+-#ifdef FP_ILOGB0
+-      if(current_precision == FP_ILOGB0)
++      if(current_precision <= (std::numeric_limits<typename T::exponent_type>::min)() + 1)
+          break;
+-#endif
+    }
+    if(b_neg)
+       result.negate();
+@@ -681,10 +679,8 @@ void eval_atan(T& result, const T& x)
+       eval_multiply(s, t, c);
+       eval_add(result, s);
+       current_precision = eval_ilogb(s);
+-#ifdef FP_ILOGB0
+-      if(current_precision == FP_ILOGB0)
++      if(current_precision <= (std::numeric_limits<typename T::exponent_type>::min)() + 1)
+          break;
+-#endif
+    }
+    if(b_neg)
+       result.negate();
+diff --git a/test/test_sf_import_c99.cpp b/test/test_sf_import_c99.cpp
+index 8ddb901..17dd3d9 100644
+--- a/test/test_sf_import_c99.cpp
++++ b/test/test_sf_import_c99.cpp
+@@ -1250,12 +1250,7 @@ void test_c99_appendix_F()
+       BOOST_CHECK(isnan(val));
+    }
+    // F.9.3.5:
+-   int fp_ilogb0 =
+-#ifdef FP_ILOGB0
+-      FP_ILOGB0;
+-#else
+-      INT_MIN;
+-#endif
++   int fp_ilogb0 = (std::numeric_limits<typename T::backend_type::exponent_type>::min)();
+    int fp_ilogbnan = 
+ #ifdef FP_ILOGBNAN
+       FP_ILOGBNAN;




More information about the pkg-boost-commits mailing list