diff --git a/include/boost/multiprecision/detail/mp_number_compare.hpp b/include/boost/multiprecision/detail/mp_number_compare.hpp new file mode 100644 index 00000000..909d4af8 --- /dev/null +++ b/include/boost/multiprecision/detail/mp_number_compare.hpp @@ -0,0 +1,488 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2012 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MP_COMPARE_HPP +#define BOOST_MP_COMPARE_HPP + +// +// Comparison operators for mp_number. +// + +namespace boost{ namespace multiprecision{ + +namespace default_ops{ + +template +inline bool eval_eq(const B& a, const B& b) +{ + return a.compare(b) == 0; +} +template +inline typename enable_if_c<(is_arithmetic::value && is_convertible::value), bool>::type eval_eq(const B& a, const A& b) +{ + B t(b); + return eval_eq(a, t); +} +template +inline typename enable_if_c<(is_arithmetic::value && !is_convertible::value), bool>::type eval_eq(const B& a, const A& b) +{ + B t; + t = b; + return eval_eq(a, t); +} + +template +inline bool eval_lt(const B& a, const B& b) +{ + return a.compare(b) < 0; +} +template +inline typename enable_if_c<(is_arithmetic::value && is_convertible::value), bool>::type eval_lt(const B& a, const A& b) +{ + B t(b); + return eval_lt(a, t); +} +template +inline typename enable_if_c<(is_arithmetic::value && !is_convertible::value), bool>::type eval_lt(const B& a, const A& b) +{ + B t; + t = b; + return eval_lt(a, t); +} + +template +inline bool eval_gt(const B& a, const B& b) +{ + return a.compare(b) > 0; +} +template +inline typename enable_if_c<(is_arithmetic::value && is_convertible::value), bool>::type eval_gt(const B& a, const A& b) +{ + B t(b); + return eval_gt(a, t); +} +template +inline typename enable_if_c<(is_arithmetic::value && !is_convertible::value), bool>::type eval_gt(const B& a, const A& b) +{ + B t; + t = b; + return eval_gt(a, t); +} + +} + +template +inline bool operator == (const mp_number& a, const mp_number& b) +{ + using default_ops::eval_eq; + return eval_eq(a.backend(), b.backend()); +} +template +inline typename enable_if_c<(is_convertible >::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator == (const mp_number& a, const Arithmetic& b) +{ + typedef typename detail::canonical::type ct; + using default_ops::eval_eq; + return eval_eq(a.backend(), ct(b)); +} +template +inline typename enable_if, typename detail::mp_exp::result_type>, bool>::type + operator == (const mp_number& a, const detail::mp_exp& b) +{ + using default_ops::eval_eq; + typename detail::mp_exp::result_type t(b); + return eval_eq(a.backend(), t.backend()); +} +template +inline typename enable_if_c<(is_convertible >::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator == (const Arithmetic& a, const mp_number& b) +{ + typedef typename detail::canonical::type ct; + using default_ops::eval_eq; + return eval_eq(b.backend(), ct(a)); +} +template +inline typename enable_if_c<(is_convertible::result_type>::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator == (const Arithmetic& a, const detail::mp_exp& b) +{ + typedef typename detail::mp_exp::result_type result_type; + typedef typename detail::canonical::type ct; + using default_ops::eval_eq; + result_type t(b); + return eval_eq(t.backend(), ct(a)); +} +template +inline typename enable_if, typename detail::mp_exp::result_type>, bool>::type + operator == (const detail::mp_exp& a, const mp_number& b) +{ + using default_ops::eval_eq; + typename detail::mp_exp::result_type t(a); + return eval_eq(t.backend(), b.backend()); +} +template +inline typename enable_if_c<(is_convertible::result_type>::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator == (const detail::mp_exp& a, const Arithmetic& b) +{ + typedef typename detail::mp_exp::result_type result_type; + typedef typename detail::canonical::type ct; + using default_ops::eval_eq; + result_type t(a); + return eval_eq(t.backend(), ct(b)); +} +template +inline typename enable_if::result_type, typename detail::mp_exp::result_type>, bool>::type + operator == (const detail::mp_exp& a, const detail::mp_exp& b) +{ + using default_ops::eval_eq; + typename detail::mp_exp::result_type t(a); + typename detail::mp_exp::result_type t2(b); + return eval_eq(t.backend(), t2.backend()); +} + +template +inline bool operator != (const mp_number& a, const mp_number& b) +{ + using default_ops::eval_eq; + return !eval_eq(a.backend(), b.backend()); +} +template +inline typename enable_if_c<(is_convertible >::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator != (const mp_number& a, const Arithmetic& b) +{ + typedef typename detail::canonical::type ct; + using default_ops::eval_eq; + return !eval_eq(a.backend(), ct(b)); +} +template +inline typename enable_if, typename detail::mp_exp::result_type>, bool>::type + operator != (const mp_number& a, const detail::mp_exp& b) +{ + using default_ops::eval_eq; + typename detail::mp_exp::result_type t(b); + return !eval_eq(a.backend(), t.backend()); +} +template +inline typename enable_if_c<(is_convertible >::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator != (const Arithmetic& a, const mp_number& b) +{ + typedef typename detail::canonical::type ct; + using default_ops::eval_eq; + return !eval_eq(b.backend(), ct(a)); +} +template +inline typename enable_if_c<(is_convertible::result_type>::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator != (const Arithmetic& a, const detail::mp_exp& b) +{ + typedef typename detail::mp_exp::result_type result_type; + typedef typename detail::canonical::type ct; + using default_ops::eval_eq; + result_type t(b); + return !eval_eq(t.backend(), ct(a)); +} +template +inline typename enable_if, typename detail::mp_exp::result_type>, bool>::type + operator != (const detail::mp_exp& a, const mp_number& b) +{ + using default_ops::eval_eq; + typename detail::mp_exp::result_type t(a); + return !eval_eq(t.backend(), b.backend()); +} +template +inline typename enable_if_c<(is_convertible::result_type>::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator != (const detail::mp_exp& a, const Arithmetic& b) +{ + typedef typename detail::mp_exp::result_type result_type; + typedef typename detail::canonical::type ct; + using default_ops::eval_eq; + result_type t(a); + return !eval_eq(t.backend(), ct(b)); +} +template +inline typename enable_if::result_type, typename detail::mp_exp::result_type>, bool>::type + operator != (const detail::mp_exp& a, const detail::mp_exp& b) +{ + using default_ops::eval_eq; + typename detail::mp_exp::result_type t(a); + typename detail::mp_exp::result_type t2(b); + return !eval_eq(t.backend(), t2.backend()); +} + +template +inline bool operator < (const mp_number& a, const mp_number& b) +{ + using default_ops::eval_lt; + return eval_lt(a.backend(), b.backend()); +} +template +inline typename enable_if_c<(is_convertible >::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator < (const mp_number& a, const Arithmetic& b) +{ + typedef typename detail::canonical::type ct; + using default_ops::eval_lt; + return eval_lt(a.backend(), ct(b)); +} +template +inline typename enable_if, typename detail::mp_exp::result_type>, bool>::type + operator < (const mp_number& a, const detail::mp_exp& b) +{ + using default_ops::eval_lt; + typename detail::mp_exp::result_type t(b); + return eval_lt(a.backend(), t.backend()); +} +template +inline typename enable_if_c<(is_convertible >::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator < (const Arithmetic& a, const mp_number& b) +{ + typedef typename detail::canonical::type ct; + using default_ops::eval_gt; + return eval_gt(b.backend(), ct(a)); +} +template +inline typename enable_if_c<(is_convertible::result_type>::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator < (const Arithmetic& a, const detail::mp_exp& b) +{ + typedef typename detail::mp_exp::result_type result_type; + typedef typename detail::canonical::type ct; + using default_ops::eval_gt; + result_type t(b); + return eval_gt(t.backend(), ct(a)); +} +template +inline typename enable_if, typename detail::mp_exp::result_type>, bool>::type + operator < (const detail::mp_exp& a, const mp_number& b) +{ + using default_ops::eval_lt; + typename detail::mp_exp::result_type t(a); + return eval_lt(t.backend(), b.backend()); +} +template +inline typename enable_if_c<(is_convertible::result_type>::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator < (const detail::mp_exp& a, const Arithmetic& b) +{ + typedef typename detail::mp_exp::result_type result_type; + typedef typename detail::canonical::type ct; + using default_ops::eval_lt; + result_type t(a); + return eval_lt(t.backend(), ct(b)); +} +template +inline typename enable_if::result_type, typename detail::mp_exp::result_type>, bool>::type + operator < (const detail::mp_exp& a, const detail::mp_exp& b) +{ + using default_ops::eval_lt; + typename detail::mp_exp::result_type t(a); + typename detail::mp_exp::result_type t2(b); + return eval_lt(t.backend(), t2.backend()); +} + +template +inline bool operator > (const mp_number& a, const mp_number& b) +{ + using default_ops::eval_gt; + return eval_gt(a.backend(), b.backend()); +} +template +inline typename enable_if_c<(is_convertible >::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator > (const mp_number& a, const Arithmetic& b) +{ + typedef typename detail::canonical::type ct; + using default_ops::eval_gt; + return eval_gt(a.backend(), ct(b)); +} +template +inline typename enable_if, typename detail::mp_exp::result_type>, bool>::type + operator > (const mp_number& a, const detail::mp_exp& b) +{ + using default_ops::eval_gt; + typename detail::mp_exp::result_type t(b); + return eval_gt(a.backend(), t.backend()); +} +template +inline typename enable_if_c<(is_convertible >::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator > (const Arithmetic& a, const mp_number& b) +{ + typedef typename detail::canonical::type ct; + using default_ops::eval_lt; + return eval_lt(b.backend(), ct(a)); +} +template +inline typename enable_if_c<(is_convertible::result_type>::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator > (const Arithmetic& a, const detail::mp_exp& b) +{ + typedef typename detail::mp_exp::result_type result_type; + typedef typename detail::canonical::type ct; + using default_ops::eval_lt; + result_type t(b); + return eval_lt(t.backend(), ct(a)); +} +template +inline typename enable_if, typename detail::mp_exp::result_type>, bool>::type + operator > (const detail::mp_exp& a, const mp_number& b) +{ + using default_ops::eval_gt; + typename detail::mp_exp::result_type t(a); + return eval_gt(t.backend(), b.backend()); +} +template +inline typename enable_if_c<(is_convertible::result_type>::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator > (const detail::mp_exp& a, const Arithmetic& b) +{ + typedef typename detail::mp_exp::result_type result_type; + typedef typename detail::canonical::type ct; + using default_ops::eval_gt; + result_type t(a); + return eval_gt(t.backend(), ct(b)); +} +template +inline typename enable_if::result_type, typename detail::mp_exp::result_type>, bool>::type + operator > (const detail::mp_exp& a, const detail::mp_exp& b) +{ + using default_ops::eval_gt; + typename detail::mp_exp::result_type t(a); + typename detail::mp_exp::result_type t2(b); + return eval_gt(t.backend(), t2.backend()); +} + +template +inline bool operator <= (const mp_number& a, const mp_number& b) +{ + using default_ops::eval_gt; + return !eval_gt(a.backend(), b.backend()); +} +template +inline typename enable_if_c<(is_convertible >::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator <= (const mp_number& a, const Arithmetic& b) +{ + typedef typename detail::canonical::type ct; + using default_ops::eval_gt; + return !eval_gt(a.backend(), ct(b)); +} +template +inline typename enable_if, typename detail::mp_exp::result_type>, bool>::type + operator <= (const mp_number& a, const detail::mp_exp& b) +{ + using default_ops::eval_gt; + typename detail::mp_exp::result_type t(b); + return !eval_gt(a.backend(), t.backend()); +} +template +inline typename enable_if_c<(is_convertible >::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator <= (const Arithmetic& a, const mp_number& b) +{ + typedef typename detail::canonical::type ct; + using default_ops::eval_lt; + return !eval_lt(b.backend(), ct(a)); +} +template +inline typename enable_if_c<(is_convertible::result_type>::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator <= (const Arithmetic& a, const detail::mp_exp& b) +{ + typedef typename detail::mp_exp::result_type result_type; + typedef typename detail::canonical::type ct; + using default_ops::eval_lt; + result_type t(b); + return !eval_lt(t.backend(), ct(a)); +} +template +inline typename enable_if, typename detail::mp_exp::result_type>, bool>::type + operator <= (const detail::mp_exp& a, const mp_number& b) +{ + using default_ops::eval_gt; + typename detail::mp_exp::result_type t(a); + return !eval_gt(t.backend(), b.backend()); +} +template +inline typename enable_if_c<(is_convertible::result_type>::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator <= (const detail::mp_exp& a, const Arithmetic& b) +{ + typedef typename detail::mp_exp::result_type result_type; + typedef typename detail::canonical::type ct; + using default_ops::eval_gt; + result_type t(a); + return !eval_gt(t.backend(), ct(b)); +} +template +inline typename enable_if::result_type, typename detail::mp_exp::result_type>, bool>::type + operator <= (const detail::mp_exp& a, const detail::mp_exp& b) +{ + using default_ops::eval_gt; + typename detail::mp_exp::result_type t(a); + typename detail::mp_exp::result_type t2(b); + return !eval_gt(t.backend(), t2.backend()); +} + +template +inline bool operator >= (const mp_number& a, const mp_number& b) +{ + using default_ops::eval_lt; + return !eval_lt(a.backend(), b.backend()); +} +template +inline typename enable_if_c<(is_convertible >::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator >= (const mp_number& a, const Arithmetic& b) +{ + typedef typename detail::canonical::type ct; + using default_ops::eval_lt; + return !eval_lt(a.backend(), ct(b)); +} +template +inline typename enable_if, typename detail::mp_exp::result_type>, bool>::type + operator >= (const mp_number& a, const detail::mp_exp& b) +{ + using default_ops::eval_lt; + typename detail::mp_exp::result_type t(b); + return !eval_lt(a.backend(), t.backend()); +} +template +inline typename enable_if_c<(is_convertible >::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator >= (const Arithmetic& a, const mp_number& b) +{ + typedef typename detail::canonical::type ct; + using default_ops::eval_gt; + return !eval_gt(b.backend(), ct(a)); +} +template +inline typename enable_if_c<(is_convertible::result_type>::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator >= (const Arithmetic& a, const detail::mp_exp& b) +{ + typedef typename detail::mp_exp::result_type result_type; + typedef typename detail::canonical::type ct; + using default_ops::eval_gt; + result_type t(b); + return !eval_gt(t.backend(), ct(a)); +} +template +inline typename enable_if, typename detail::mp_exp::result_type>, bool>::type + operator >= (const detail::mp_exp& a, const mp_number& b) +{ + using default_ops::eval_lt; + typename detail::mp_exp::result_type t(a); + return !eval_lt(t.backend(), b.backend()); +} +template +inline typename enable_if_c<(is_convertible::result_type>::value && !is_mp_number_expression::value && !is_mp_number::value), bool>::type + operator >= (const detail::mp_exp& a, const Arithmetic& b) +{ + typedef typename detail::mp_exp::result_type result_type; + typedef typename detail::canonical::type ct; + using default_ops::eval_lt; + result_type t(a); + return !eval_lt(t.backend(), ct(b)); +} +template +inline typename enable_if::result_type, typename detail::mp_exp::result_type>, bool>::type + operator >= (const detail::mp_exp& a, const detail::mp_exp& b) +{ + using default_ops::eval_lt; + typename detail::mp_exp::result_type t(a); + typename detail::mp_exp::result_type t2(b); + return !eval_lt(t.backend(), t2.backend()); +} + + +}} // namespaces + +#endif // BOOST_MP_COMPARE_HPP + diff --git a/include/boost/multiprecision/mp_number.hpp b/include/boost/multiprecision/mp_number.hpp index 3d93418e..4a8ee16d 100644 --- a/include/boost/multiprecision/mp_number.hpp +++ b/include/boost/multiprecision/mp_number.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include // stream operators #include // EOF @@ -1630,14 +1631,13 @@ struct is_valid_comparison : public boost::multiprecision::detail::is_valid_comp } - +/* template inline typename boost::enable_if, bool>::type operator == (const Exp1& a, const Exp2& b) { return 0 == detail::mp_number_compare(a, b); } - template inline typename boost::enable_if, bool>::type operator != (const Exp1& a, const Exp2& b) @@ -1672,7 +1672,7 @@ inline typename boost::enable_if, bool>: { return 0 < detail::mp_number_compare(a, b); } - +*/ template inline std::ostream& operator << (std::ostream& os, const mp_number& r) { diff --git a/performance/Jamfile.v2 b/performance/Jamfile.v2 index 66d35e7f..eb349c69 100644 --- a/performance/Jamfile.v2 +++ b/performance/Jamfile.v2 @@ -69,6 +69,8 @@ exe sf_performance : sf_performance.cpp /boost/system//boost_system /boost/chron TEST_CPP_DEC_FLOAT msvc:-bigobj ; + +exe delaunay_test : delaunay_test.cpp /boost/system//boost_system /boost/chrono//boost_chrono ; obj obj_linpack_benchmark_mpfr : linpack-benchmark.cpp : release @@ -118,4 +120,6 @@ install miller_rabin_install : miller_rabin_performance : . ; install performance_test_install : performance_test : . ; install sf_performance_install : sf_performance : . ; install . : linpack_benchmark_double linpack_benchmark_cpp_float linpack_benchmark_mpf linpack_benchmark_mpfr ; +install delaunay_install : delaunay_test : . ; + diff --git a/performance/arithmetic_backend.hpp b/performance/arithmetic_backend.hpp index 69176f3c..e3d5f4d1 100644 --- a/performance/arithmetic_backend.hpp +++ b/performance/arithmetic_backend.hpp @@ -18,6 +18,11 @@ namespace boost{ namespace multiprecision{ namespace backends{ +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4389 4244 4018 4244 4127) +#endif + template struct arithmetic_backend { @@ -46,7 +51,14 @@ struct arithmetic_backend } arithmetic_backend& operator = (const char* s) { - m_value = boost::lexical_cast(s); + try + { + m_value = boost::lexical_cast(s); + } + catch(const bad_lexical_cast&) + { + throw std::runtime_error(std::string("Unable to interpret the string provided: \"") + s + std::string("\" as a compatible number type.")); + } return *this; } void swap(arithmetic_backend& o) @@ -57,12 +69,20 @@ struct arithmetic_backend { std::stringstream ss; ss.flags(f); - ss << std::setprecision(digits) << m_value; + ss << std::setprecision(digits ? digits : std::numeric_limits::digits10 + 4) << m_value; return ss.str(); } + void do_negate(const mpl::true_&) + { + m_value = 1 + ~m_value; + } + void do_negate(const mpl::false_&) + { + m_value = -m_value; + } void negate() { - m_value = -m_value; + do_negate(is_unsigned()); } int compare(const arithmetic_backend& o)const { @@ -85,6 +105,37 @@ inline void eval_convert_to(R* result, const arithmetic_backend& bac *result = backend.data(); } +template +inline bool eval_eq(const arithmetic_backend& a, const arithmetic_backend& b) +{ + return a.data() == b.data(); +} +template +inline bool eval_eq(const arithmetic_backend& a, const A2& b) +{ + return a.data() == b; +} +template +inline bool eval_lt(const arithmetic_backend& a, const arithmetic_backend& b) +{ + return a.data() < b.data(); +} +template +inline bool eval_lt(const arithmetic_backend& a, const A2& b) +{ + return a.data() < b; +} +template +inline bool eval_gt(const arithmetic_backend& a, const arithmetic_backend& b) +{ + return a.data() > b.data(); +} +template +inline bool eval_gt(const arithmetic_backend& a, const A2& b) +{ + return a.data() > b; +} + template inline void eval_add(arithmetic_backend& result, const arithmetic_backend& o) { @@ -103,6 +154,8 @@ inline void eval_multiply(arithmetic_backend& result, const arithmet template inline void eval_divide(arithmetic_backend& result, const arithmetic_backend& o) { + if(!std::numeric_limits::has_infinity && !o.data()) + BOOST_THROW_EXCEPTION(std::runtime_error("Divide by zero")); result.data() /= o.data(); } @@ -124,6 +177,8 @@ inline typename enable_if >::type eval_multiply(arithmetic_bac template inline typename enable_if >::type eval_divide(arithmetic_backend& result, const A2& o) { + if(!std::numeric_limits::has_infinity && !o) + BOOST_THROW_EXCEPTION(std::runtime_error("Divide by zero")); result.data() /= o; } @@ -145,6 +200,8 @@ inline void eval_multiply(arithmetic_backend& result, const arithmet template inline void eval_divide(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) { + if(!std::numeric_limits::has_infinity && !b.data()) + BOOST_THROW_EXCEPTION(std::runtime_error("Divide by zero")); result.data() = a.data() / b.data(); } @@ -166,6 +223,8 @@ inline typename enable_if>::type eval_multiply(arithmetic_back template inline typename enable_if>::type eval_divide(arithmetic_backend& result, const arithmetic_backend& a, const A2& b) { + if(!std::numeric_limits::has_infinity && !b) + BOOST_THROW_EXCEPTION(std::runtime_error("Divide by zero")); result.data() = a.data() / b; } @@ -181,10 +240,15 @@ inline int eval_get_sign(const arithmetic_backend& val) return val.data() == 0 ? 0 : val.data() < 0 ? -1 : 1; } +template +inline typename enable_if, T>::type abs(T v) { return v; } + template inline void eval_abs(arithmetic_backend& result, const arithmetic_backend& o) { - result.data() = std::abs(o.data()); + using std::abs; + using boost::multiprecision::backends::abs; + result.data() = abs(o.data()); } template @@ -234,6 +298,20 @@ inline void eval_round(arithmetic_backend& result, const arithmetic_ result.data() = round(o.data()); } +template +inline void eval_frexp(arithmetic_backend& result, const arithmetic_backend& a, int* v) +{ + BOOST_MATH_STD_USING + result.data() = frexp(a.data(), v); +} + +template +inline void eval_ldexp(arithmetic_backend& result, const arithmetic_backend& a, int v) +{ + BOOST_MATH_STD_USING + result.data() = ldexp(a.data(), v); +} + template inline void eval_exp(arithmetic_backend& result, const arithmetic_backend& o) { @@ -339,10 +417,71 @@ inline void eval_atan2(arithmetic_backend& result, const arithmetic_ result.data() = atan2(a.data(), b.data()); } +template +inline void eval_left_shift(arithmetic_backend& result, I val) +{ + result.data() <<= val; +} + +template +inline void eval_right_shift(arithmetic_backend& result, I val) +{ + result.data() >>= val; +} + +template +inline void eval_modulus(arithmetic_backend& result, const arithmetic_backend& a) +{ + result.data() %= a.data(); +} + +template +inline void eval_bitwise_and(arithmetic_backend& result, const arithmetic_backend& a) +{ + result.data() &= a.data(); +} + +template +inline void eval_bitwise_or(arithmetic_backend& result, const arithmetic_backend& a) +{ + result.data() |= a.data(); +} + +template +inline void eval_bitwise_xor(arithmetic_backend& result, const arithmetic_backend& a) +{ + result.data() ^= a.data(); +} + +template +inline void eval_complement(arithmetic_backend& result, const arithmetic_backend& a) +{ + result.data() = ~a.data(); +} + +template +inline void eval_gcd(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) +{ + result.data() = boost::math::gcd(a.data(), b.data()); +} + +template +inline void eval_lcm(arithmetic_backend& result, const arithmetic_backend& a, const arithmetic_backend& b) +{ + result.data() = boost::math::lcm(a.data(), b.data()); +} + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + } // namespace backends using boost::multiprecision::backends::arithmetic_backend; +template +struct number_category > : public mpl::int_::value ? number_kind_integer : number_kind_floating_point>{}; + }} // namespaces namespace boost{ namespace math{ namespace tools{ @@ -394,4 +533,6 @@ public: } +#include + #endif diff --git a/performance/sf_performance.cpp b/performance/sf_performance.cpp index 2277fd35..b6b056bf 100644 --- a/performance/sf_performance.cpp +++ b/performance/sf_performance.cpp @@ -257,10 +257,15 @@ int main() // Comparison for builtin floats: // #ifdef TEST_FLOAT - time_proc("double", test_bessel); - time_proc("real_concept", test_bessel); - time_proc("arithmetic_backend", test_bessel > >); - time_proc("arithmetic_backend - no expression templates", test_bessel, false> >); + time_proc("Bessel Functions - double", test_bessel); + time_proc("Bessel Functions - real_concept", test_bessel); + time_proc("Bessel Functions - arithmetic_backend", test_bessel > >); + time_proc("Bessel Functions - arithmetic_backend - no expression templates", test_bessel, false> >); + + time_proc("Non-central T - double", test_nct); + time_proc("Non-central T - real_concept", test_nct); + time_proc("Non-central T - arithmetic_backend", test_nct > >); + time_proc("Non-central T - arithmetic_backend - no expression templates", test_nct, false> >); #endif // diff --git a/test/test_arithmetic.cpp b/test/test_arithmetic.cpp index 352aee53..c85ae630 100644 --- a/test/test_arithmetic.cpp +++ b/test/test_arithmetic.cpp @@ -18,7 +18,7 @@ #if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && \ !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) \ && !defined(TEST_TOMMATH) && !defined(TEST_TOMMATH_BOOST_RATIONAL) && !defined(TEST_MPZ_BOOST_RATIONAL)\ - && !defined(TEST_CPP_INT) && !defined(TEST_CPP_INT_BR) + && !defined(TEST_CPP_INT) && !defined(TEST_CPP_INT_BR) && !defined(TEST_ARITHMETIC_BACKEND) # define TEST_MPF_50 # define TEST_MPF # define TEST_BACKEND @@ -30,6 +30,7 @@ # define TEST_TOMMATH # define TEST_CPP_INT # define TEST_CPP_INT_BR +# define TEST_ARITHMETIC_BACKEND #ifdef _MSC_VER #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") @@ -40,6 +41,9 @@ #endif +#if defined(TEST_ARITHMETIC_BACKEND) +# include "../performance/arithmetic_backend.hpp" +#endif #if defined(TEST_MPF_50) || defined(TEST_MPF) || defined(TEST_MPZ) || defined(TEST_MPQ) || defined(TEST_MPZ_BOOST_RATIONAL) #include #include @@ -628,7 +632,10 @@ void test_negative_mixed(boost::mpl::true_ const&) Num tol = 0; #endif std::ios_base::fmtflags f = boost::is_floating_point::value ? std::ios_base::scientific : std::ios_base::fmtflags(0); - BOOST_TEST_CLOSE(n1, boost::lexical_cast(Real(n1).str(0, f)), tol); + if(std::numeric_limits::digits <= std::numeric_limits::digits) + { + BOOST_TEST_CLOSE(n1, boost::lexical_cast(Real(n1).str(0, f)), tol); + } BOOST_TEST_CLOSE(n2, boost::lexical_cast(Real(n2).str(0, f)), 0); BOOST_TEST_CLOSE(n3, boost::lexical_cast(Real(n3).str(0, f)), 0); BOOST_TEST_CLOSE(n4, boost::lexical_cast(Real(n4).str(0, f)), 0); @@ -693,6 +700,10 @@ template void test_mixed() { typedef typename lexical_cast_target_type::type target_type; + + if(std::numeric_limits::digits < std::numeric_limits::digits) + return; + std::cout << "Testing mixed arithmetic with type: " << typeid(Real).name() << " and " << typeid(Num).name() << std::endl; Num n1 = static_cast(1uLL << (std::numeric_limits::digits - 1)); Num n2 = 1; @@ -730,7 +741,10 @@ void test_mixed() Num tol = 0; #endif std::ios_base::fmtflags f = boost::is_floating_point::value ? std::ios_base::scientific : std::ios_base::fmtflags(0); - BOOST_TEST_CLOSE(n1, boost::lexical_cast(Real(n1).str(0, f)), tol); + if(std::numeric_limits::digits <= std::numeric_limits::digits) + { + BOOST_TEST_CLOSE(n1, boost::lexical_cast(Real(n1).str(0, f)), tol); + } BOOST_TEST_CLOSE(n2, boost::lexical_cast(Real(n2).str(0, f)), 0); BOOST_TEST_CLOSE(n3, boost::lexical_cast(Real(n3).str(0, f)), 0); BOOST_TEST_CLOSE(n4, boost::lexical_cast(Real(n4).str(0, f)), 0); @@ -1126,6 +1140,11 @@ void test() int main() { +#ifdef TEST_ARITHMETIC_BACKEND + test > >(); + test > >(); + test > >(); +#endif #ifdef TEST_BACKEND test >(); #endif