[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