From c3d0d2beadf01fa2b92279c29efbc574768b2633 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Tue, 20 Sep 2011 12:36:22 +0000 Subject: [PATCH] Optimise comparison to zero. Remove unnecessary static asserts - even floats are incrementable. Fix some of the default function methods, and add fmod. Add mpq comparison and conversion routines. Add mpfr lanczos support. Add std lib function support for big_number_architype. Update comparison tests. [SVN r74479] --- include/boost/math/big_number.hpp | 7 +- include/boost/math/big_number/default_ops.hpp | 25 ++++++- include/boost/math/big_number/gmp.hpp | 22 +++++++ include/boost/math/big_number/mpfr.hpp | 24 +++++++ .../math/concepts/big_number_architypes.hpp | 65 +++++++++++++++++++ math/test/test_arithmetic.cpp | 24 +++++++ 6 files changed, 161 insertions(+), 6 deletions(-) diff --git a/include/boost/math/big_number.hpp b/include/boost/math/big_number.hpp index 664aec72..b2f2612a 100644 --- a/include/boost/math/big_number.hpp +++ b/include/boost/math/big_number.hpp @@ -224,7 +224,6 @@ public: // big_number& operator++() { - BOOST_STATIC_ASSERT_MSG(is_extended_integer::value, "The increment operation is only valid for integer types"); using big_num_default_ops::increment; increment(m_backend); return *this; @@ -232,7 +231,6 @@ public: big_number& operator--() { - BOOST_STATIC_ASSERT_MSG(is_extended_integer::value, "The increment operation is only valid for integer types"); using big_num_default_ops::decrement; decrement(m_backend); return *this; @@ -240,7 +238,6 @@ public: big_number operator++(int) { - BOOST_STATIC_ASSERT_MSG(is_extended_integer::value, "The increment operation is only valid for integer types"); using big_num_default_ops::increment; self_type temp(*this); increment(m_backend); @@ -249,7 +246,6 @@ public: big_number operator--(int) { - BOOST_STATIC_ASSERT_MSG(is_extended_integer::value, "The increment operation is only valid for integer types"); using big_num_default_ops::decrement; self_type temp(*this); decrement(m_backend); @@ -439,6 +435,8 @@ public: template typename enable_if, int>::type compare(const V& o)const { + if(o == 0) + return get_sign(m_backend); return m_backend.compare(canonical_value(o)); } Backend& backend() @@ -1380,6 +1378,7 @@ private: static const Backend& canonical_value(const self_type& v){ return v.m_backend; } static const Backend& canonical_value(const self_type* v){ return v->m_backend; } static const Backend& canonical_value(self_type* v){ return v->m_backend; } + static const Backend& canonical_value(self_type& v){ return v.m_backend; } template static typename detail::canonical::type canonical_value(const V& v){ return v; } static typename detail::canonical::type canonical_value(const std::string& v){ return v.c_str(); } diff --git a/include/boost/math/big_number/default_ops.hpp b/include/boost/math/big_number/default_ops.hpp index ca14a806..da2df385 100644 --- a/include/boost/math/big_number/default_ops.hpp +++ b/include/boost/math/big_number/default_ops.hpp @@ -328,7 +328,7 @@ inline void convert_to(terminal* result, const B& backend) // Functions: // template -void eval_abs(T* result, const T& arg) +void eval_abs(T& result, const T& arg) { typedef typename T::signed_types type_list; typedef typename mpl::front::type front; @@ -337,7 +337,7 @@ void eval_abs(T* result, const T& arg) result->negate(); } template -void eval_fabs(T* result, const T& arg) +void eval_fabs(T& result, const T& arg) { typedef typename T::signed_types type_list; typedef typename mpl::front::type front; @@ -351,6 +351,26 @@ inline int eval_fpclassify(const Backend& arg) { return is_zero(arg) ? FP_ZERO : FP_NORMAL; } + +template +inline void eval_fmod(T& result, const T& a, const T& b) +{ + if((&result == &a) || (&result == &b)) + { + T temp; + eval_fmod(temp, a, b); + result = temp; + } + T n; + divide(result, a, b); + if(get_sign(a) < 0) + eval_ceil(n, result); + else + eval_floor(n, result); + multiply(n, b); + subtract(result, a, n); +} + // // These have to implemented by the backend, declared here so that our macro generated code compiles OK. // @@ -828,6 +848,7 @@ UNARY_OP_FUNCTOR(tanh) HETERO_BINARY_OP_FUNCTOR(ldexp, int) HETERO_BINARY_OP_FUNCTOR(frexp, int*) BINARY_OP_FUNCTOR(pow) +BINARY_OP_FUNCTOR(fmod) #undef BINARY_OP_FUNCTOR #undef UNARY_OP_FUNCTOR diff --git a/include/boost/math/big_number/gmp.hpp b/include/boost/math/big_number/gmp.hpp index cfb114aa..3c32b4ea 100644 --- a/include/boost/math/big_number/gmp.hpp +++ b/include/boost/math/big_number/gmp.hpp @@ -1225,6 +1225,14 @@ struct gmp_rational d = v; return compare(d); } + int compare(unsigned long v) + { + return mpq_cmp_ui(m_data, v, 1); + } + int compare(long v) + { + return mpq_cmp_si(m_data, v, 1); + } mpq_t& data() { return m_data; } const mpq_t& data()const { return m_data; } protected: @@ -1277,6 +1285,20 @@ inline void convert_to(double* result, const gmp_rational& val) *result = mpq_get_d(val.data()); } +inline void convert_to(long* result, const gmp_rational& val) +{ + double r; + convert_to(&r, val); + *result = r; +} + +inline void convert_to(unsigned long* result, const gmp_rational& val) +{ + double r; + convert_to(&r, val); + *result = r; +} + inline void eval_abs(gmp_rational& result, const gmp_rational& val) { mpq_abs(result.data(), val.data()); diff --git a/include/boost/math/big_number/mpfr.hpp b/include/boost/math/big_number/mpfr.hpp index 3020edf5..e03f05da 100644 --- a/include/boost/math/big_number/mpfr.hpp +++ b/include/boost/math/big_number/mpfr.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -739,6 +740,29 @@ typedef big_number > mpfr_real_500; typedef big_number > mpfr_real_1000; typedef big_number > mpfr_real; +namespace lanczos{ + +template +struct lanczos >, Policy> +{ + typedef typename mpl::if_c< + Digits10 <= 36, + lanczos22UDT, + typename mpl::if_c< + Digits10 <= 50, + lanczos31UDT, + typename mpl::if_c< + Digits10 <= 110, + lanczos61UDT, + undefined_lanczos + >::type + >::type + >::type type; +}; + +} // namespace lanczos + + }} // namespaces namespace std{ diff --git a/include/boost/math/concepts/big_number_architypes.hpp b/include/boost/math/concepts/big_number_architypes.hpp index 66d79fc4..26a7a4b6 100644 --- a/include/boost/math/concepts/big_number_architypes.hpp +++ b/include/boost/math/concepts/big_number_architypes.hpp @@ -188,6 +188,71 @@ inline int eval_fpclassify(const big_number_backend_real_architype& arg) return boost::math::fpclassify(arg.m_value); } +inline void eval_pow(big_number_backend_real_architype& result, const big_number_backend_real_architype& b, const big_number_backend_real_architype& e) +{ + result = std::pow(b.m_value, e.m_value); +} + +inline void eval_pow(big_number_backend_real_architype& result, const big_number_backend_real_architype& b, int e) +{ + result = std::pow(b.m_value, e); +} + +inline void eval_exp(big_number_backend_real_architype& result, const big_number_backend_real_architype& arg) +{ + result = std::exp(arg.m_value); +} + +inline void eval_log(big_number_backend_real_architype& result, const big_number_backend_real_architype& arg) +{ + result = std::log(arg.m_value); +} + +inline void eval_sin(big_number_backend_real_architype& result, const big_number_backend_real_architype& arg) +{ + result = std::sin(arg.m_value); +} + +inline void eval_cos(big_number_backend_real_architype& result, const big_number_backend_real_architype& arg) +{ + result = std::cos(arg.m_value); +} + +inline void eval_tan(big_number_backend_real_architype& result, const big_number_backend_real_architype& arg) +{ + result = std::tan(arg.m_value); +} + +inline void eval_asin(big_number_backend_real_architype& result, const big_number_backend_real_architype& arg) +{ + result = std::asin(arg.m_value); +} + +inline void eval_acos(big_number_backend_real_architype& result, const big_number_backend_real_architype& arg) +{ + result = std::acos(arg.m_value); +} + +inline void eval_atan(big_number_backend_real_architype& result, const big_number_backend_real_architype& arg) +{ + result = std::atan(arg.m_value); +} + +inline void eval_sinh(big_number_backend_real_architype& result, const big_number_backend_real_architype& arg) +{ + result = std::sinh(arg.m_value); +} + +inline void eval_cosh(big_number_backend_real_architype& result, const big_number_backend_real_architype& arg) +{ + result = std::cosh(arg.m_value); +} + +inline void eval_tanh(big_number_backend_real_architype& result, const big_number_backend_real_architype& arg) +{ + result = std::tanh(arg.m_value); +} + typedef boost::math::big_number big_number_real_architype; }}} // namespaces diff --git a/math/test/test_arithmetic.cpp b/math/test/test_arithmetic.cpp index a8635716..fa795461 100644 --- a/math/test/test_arithmetic.cpp +++ b/math/test/test_arithmetic.cpp @@ -345,6 +345,18 @@ void test_negative_mixed(boost::mpl::true_ const&) Num n3 = 0; Num n4 = -20; Num n5 = -8; + BOOST_TEST((Real(n2) < 0) == true); + BOOST_TEST((Real(n2) <= 0) == true); + BOOST_TEST((Real(n2) > 0) == false); + BOOST_TEST((Real(n2) >= 0) == false); + BOOST_TEST((Real(n2) == 0) == false); + BOOST_TEST((Real(n2) != 0) == true); + BOOST_TEST((Real(n2) == n2) == true); + BOOST_TEST((Real(n2) != n2) == false); + BOOST_TEST((Real(n2) >= n2) == true); + BOOST_TEST((Real(n2) <= n2) == true); + BOOST_TEST((Real(n2) > n2) == false); + BOOST_TEST((Real(n2) < n2) == false); // Default construct: BOOST_TEST(Real(n1) == n1); BOOST_TEST(Real(n2) == n2); @@ -425,6 +437,18 @@ void test_mixed() Num n3 = 0; Num n4 = 20; Num n5 = 8; + BOOST_TEST((Real(n2) < 0) == false); + BOOST_TEST((Real(n2) <= 0) == false); + BOOST_TEST((Real(n2) > 0) == true); + BOOST_TEST((Real(n2) >= 0) == true); + BOOST_TEST((Real(n2) == 0) == false); + BOOST_TEST((Real(n2) != 0) == true); + BOOST_TEST((Real(n2) == n2) == true); + BOOST_TEST((Real(n2) != n2) == false); + BOOST_TEST((Real(n2) >= n2) == true); + BOOST_TEST((Real(n2) <= n2) == true); + BOOST_TEST((Real(n2) > n2) == false); + BOOST_TEST((Real(n2) < n2) == false); // Default construct: BOOST_TEST(Real(n1) == n1); BOOST_TEST(Real(n2) == n2);