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]
This commit is contained in:
John Maddock
2011-09-20 12:36:22 +00:00
parent 4af7f865b0
commit c3d0d2bead
6 changed files with 161 additions and 6 deletions

View File

@@ -224,7 +224,6 @@ public:
//
big_number& operator++()
{
BOOST_STATIC_ASSERT_MSG(is_extended_integer<Backend>::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<Backend>::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<Backend>::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<Backend>::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 <class V>
typename enable_if<is_arithmetic<V>, 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 <class V>
static typename detail::canonical<V, Backend>::type canonical_value(const V& v){ return v; }
static typename detail::canonical<std::string, Backend>::type canonical_value(const std::string& v){ return v.c_str(); }

View File

@@ -328,7 +328,7 @@ inline void convert_to(terminal<R>* result, const B& backend)
// Functions:
//
template <class T>
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_list>::type front;
@@ -337,7 +337,7 @@ void eval_abs(T* result, const T& arg)
result->negate();
}
template <class T>
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_list>::type front;
@@ -351,6 +351,26 @@ inline int eval_fpclassify(const Backend& arg)
{
return is_zero(arg) ? FP_ZERO : FP_NORMAL;
}
template <class T>
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

View File

@@ -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());

View File

@@ -10,6 +10,7 @@
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/cstdint.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/math/bindings/detail/big_lanczos.hpp>
#include <mpfr.h>
#include <cmath>
#include <algorithm>
@@ -739,6 +740,29 @@ typedef big_number<mpfr_real_backend<500> > mpfr_real_500;
typedef big_number<mpfr_real_backend<1000> > mpfr_real_1000;
typedef big_number<mpfr_real_backend<0> > mpfr_real;
namespace lanczos{
template<unsigned Digits10, class Policy>
struct lanczos<big_number<mpfr_real_backend<Digits10> >, 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{

View File

@@ -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_backend_real_architype> big_number_real_architype;
}}} // namespaces

View File

@@ -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);