|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r85242 - in sandbox/multiprecision.cpp_bin_float: . boost boost/multiprecision libs libs/multiprecision libs/multiprecision/test
From: john_at_[hidden]
Date: 2013-08-08 13:52:19
Author: johnmaddock
Date: 2013-08-08 13:52:19 EDT (Thu, 08 Aug 2013)
New Revision: 85242
URL: http://svn.boost.org/trac/boost/changeset/85242
Log:
Initial commit.
Added:
sandbox/multiprecision.cpp_bin_float/
sandbox/multiprecision.cpp_bin_float/boost/
sandbox/multiprecision.cpp_bin_float/boost/multiprecision/
sandbox/multiprecision.cpp_bin_float/boost/multiprecision/cpp_bin_float.hpp (contents, props changed)
sandbox/multiprecision.cpp_bin_float/libs/
sandbox/multiprecision.cpp_bin_float/libs/multiprecision/
sandbox/multiprecision.cpp_bin_float/libs/multiprecision/test/
sandbox/multiprecision.cpp_bin_float/libs/multiprecision/test/test_arithmetic_cpp_bin_float_1.cpp (contents, props changed)
sandbox/multiprecision.cpp_bin_float/libs/multiprecision/test/test_cpp_bin_float.cpp (contents, props changed)
Added: sandbox/multiprecision.cpp_bin_float/boost/multiprecision/cpp_bin_float.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ sandbox/multiprecision.cpp_bin_float/boost/multiprecision/cpp_bin_float.hpp 2013-08-08 13:52:19 EDT (Thu, 08 Aug 2013) (r85242)
@@ -0,0 +1,1088 @@
+///////////////////////////////////////////////////////////////
+// Copyright 2013 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_
+
+#ifndef BOOST_MATH_CPP_BIN_FLOAT_HPP
+#define BOOST_MATH_CPP_BIN_FLOAT_HPP
+
+#include <boost/multiprecision/cpp_int.hpp>
+#include <boost/multiprecision/integer.hpp>
+#include <boost/math/special_functions/trunc.hpp>
+#include <boost/multiprecision/detail/float_string_cvt.hpp>
+
+namespace boost{ namespace multiprecision{ namespace backends{
+
+template <unsigned Bits>
+class cpp_bin_float
+{
+public:
+ typedef cpp_int_backend<Bits, Bits, unsigned_magnitude, unchecked, void> rep_type;
+ typedef cpp_int_backend<2 * Bits, 2 * Bits, unsigned_magnitude, unchecked, void> double_rep_type;
+
+ typedef typename rep_type::signed_types signed_types;
+ typedef typename rep_type::unsigned_types unsigned_types;
+ typedef boost::mpl::list<double, long double> float_types;
+ typedef int exponent_type;
+
+ static const int max_exponent = boost::integer_traits<int>::const_max - 2 * Bits;
+ static const int min_exponent = boost::integer_traits<int>::const_min + 2 * static_cast<int>(Bits);
+
+ static const int exponent_zero = max_exponent + 1;
+ static const int exponent_infinity = max_exponent + 2;
+ static const int exponent_nan = max_exponent + 3;
+
+private:
+
+ rep_type m_data;
+ int m_exponent;
+ int m_sign;
+public:
+ cpp_bin_float() : m_data(), m_exponent(exponent_nan), m_sign(false) {}
+
+ cpp_bin_float(const cpp_bin_float &o)
+ : m_data(o.m_data), m_exponent(o.m_exponent), m_sign(o.m_sign) {}
+
+ template <class Float>
+ cpp_bin_float(const Float& f, typename boost::enable_if_c<number_category<Float>::value == number_kind_floating_point>::type const* = 0)
+ : m_data(), m_exponent(0), m_sign(false)
+ {
+ *this = f;
+ }
+
+ cpp_bin_float& operator=(const cpp_bin_float &o)
+ {
+ m_data = o.m_data;
+ m_exponent = o.m_exponent;
+ m_sign = o.m_sign;
+ return *this;
+ }
+
+ template <class Float>
+ typename boost::enable_if_c<is_floating_point<Float>::value, cpp_bin_float&>::type operator=(Float f)
+ {
+ BOOST_MATH_STD_USING
+ using default_ops::eval_add;
+
+ switch((boost::math::fpclassify)(f))
+ {
+ case FP_ZERO:
+ m_data = limb_type(0);
+ m_sign = false;
+ m_exponent = exponent_zero;
+ return *this;
+ case FP_NAN:
+ m_data = limb_type(0);
+ m_sign = false;
+ m_exponent = exponent_nan;
+ return *this;
+ case FP_INFINITE:
+ m_data = limb_type(0);
+ m_sign = false;
+ m_exponent = exponent_infinity;
+ return *this;
+ }
+ if(f < 0)
+ {
+ *this = -f;
+ this->negate();
+ return *this;
+ }
+
+ typedef typename mpl::front<unsigned_types>::type ui_type;
+ m_data = static_cast<ui_type>(0u);
+ m_sign = false;
+ m_exponent = 0;
+
+ static const int bits = sizeof(int) * CHAR_BIT - 1;
+ int e;
+ f = frexp(f, &e);
+ while(f)
+ {
+ f = ldexp(f, bits);
+ e -= bits;
+ int ipart = itrunc(f);
+ f -= ipart;
+ m_exponent += bits;
+ eval_add(*this, ipart);
+ }
+ m_exponent += e;
+ return *this;
+ }
+
+ template <class Float>
+ typename boost::enable_if_c<
+ (number_category<Float>::value == number_kind_floating_point)
+ && !is_floating_point<Float>::value
+ && (std::numeric_limits<number<Float> >::radix == 2),
+ cpp_bin_float&>::type operator=(Float f)
+ {
+ BOOST_MATH_STD_USING
+ using default_ops::eval_add;
+ using default_ops::eval_get_sign;
+ using default_ops::eval_convert_to;
+ using default_ops::eval_subtract;
+
+ typedef typename boost::multiprecision::detail::canonical<int, Float>::type f_int_type;
+ typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type;
+
+ switch(eval_fpclassify(f))
+ {
+ case FP_ZERO:
+ m_data = limb_type(0);
+ m_sign = false;
+ m_exponent = exponent_zero;
+ return *this;
+ case FP_NAN:
+ m_data = limb_type(0);
+ m_sign = false;
+ m_exponent = exponent_nan;
+ return *this;
+ case FP_INFINITE:
+ m_data = limb_type(0);
+ m_sign = false;
+ m_exponent = exponent_infinity;
+ return *this;
+ }
+ if(eval_get_sign(f) < 0)
+ {
+ f.negate();
+ *this = f;
+ this->negate();
+ return *this;
+ }
+
+ typedef typename mpl::front<unsigned_types>::type ui_type;
+ m_data = static_cast<ui_type>(0u);
+ m_sign = false;
+ m_exponent = 0;
+
+ static const int bits = sizeof(int) * CHAR_BIT - 1;
+ int e;
+ eval_frexp(f, f, &e);
+ while(eval_get_sign(f) != 0)
+ {
+ eval_ldexp(f, f, bits);
+ e -= bits;
+ int ipart;
+ eval_convert_to(&ipart, f);
+ eval_subtract(f, static_cast<f_int_type>(ipart));
+ m_exponent += bits;
+ eval_add(*this, static_cast<bf_int_type>(ipart));
+ }
+ m_exponent += e;
+ if(m_exponent > max_exponent)
+ m_exponent = exponent_infinity;
+ if(m_exponent < min_exponent)
+ {
+ m_data = limb_type(0u);
+ m_exponent = exponent_zero;
+ m_sign = false;
+ }
+ else if(eval_get_sign(m_data) == 0)
+ {
+ m_exponent = exponent_zero;
+ m_sign = false;
+ }
+ return *this;
+ }
+
+ template <class I>
+ typename boost::enable_if<is_integral<I>, cpp_bin_float&>::type operator=(const I& i)
+ {
+ using default_ops::eval_bit_test;
+ if(!i)
+ {
+ m_data = static_cast<limb_type>(0);
+ m_exponent = exponent_zero;
+ m_sign = false;
+ }
+ else
+ {
+ I fi = boost::multiprecision::detail::abs(i);
+ typedef typename boost::multiprecision::detail::canonical<I, rep_type>::type ar_type;
+ m_data = static_cast<ar_type>(fi);
+ unsigned shift = msb(fi);
+ m_exponent = shift;
+ eval_left_shift(m_data, Bits - shift - 1);
+ BOOST_ASSERT(eval_bit_test(m_data, Bits-1));
+ m_sign = i < 0;
+ }
+ return *this;
+ }
+
+ cpp_bin_float& operator=(const char *s)
+ {
+ boost::multiprecision::detail::convert_from_string(*this, s);
+ return *this;
+ }
+
+ void swap(cpp_bin_float &o) BOOST_NOEXCEPT
+ {
+ m_data.swap(o.m_data);
+ std::swap(m_exponent, o.m_exponent);
+ std::swap(m_sign, o.m_sign);
+ }
+
+ std::string str(std::streamsize dig, std::ios_base::fmtflags f) const
+ {
+ if(dig == 0)
+ dig = std::numeric_limits<number<cpp_bin_float<Bits> > >::max_digits10;
+ return boost::multiprecision::detail::convert_to_string(*this, dig, f);
+ }
+
+ void negate()
+ {
+ if((m_exponent != exponent_zero) && (m_exponent != exponent_nan))
+ m_sign = !m_sign;
+ }
+
+ int compare(const cpp_bin_float &o) const BOOST_NOEXCEPT
+ {
+ if(m_sign != o.m_sign)
+ return m_sign ? -1 : 1;
+ int result;
+ if(m_exponent != o.m_exponent)
+ {
+ if(m_exponent == exponent_zero)
+ result = -1;
+ else if(o.m_exponent == exponent_zero)
+ result = 1;
+ else
+ result = m_exponent > o.m_exponent ? 1 : -1;
+ }
+ else
+ result = m_data.compare(o.m_data);
+ if(m_sign)
+ result = -result;
+ return result;
+ }
+ template <class A>
+ int compare(const A& o) const BOOST_NOEXCEPT
+ {
+ cpp_bin_float b;
+ b = o;
+ return compare(b);
+ }
+
+ rep_type& bits() { return m_data; }
+ const rep_type& bits()const { return m_data; }
+ int& exponent() { return m_exponent; }
+ const int& exponent()const { return m_exponent; }
+ int& sign() { return m_sign; }
+ const int& sign()const { return m_sign; }
+ void check_invariants()
+ {
+ using default_ops::eval_bit_test;
+ using default_ops::eval_is_zero;
+ if((m_exponent <= max_exponent) && (m_exponent >= min_exponent))
+ {
+ BOOST_ASSERT(eval_bit_test(m_data, Bits - 1));
+ }
+ else
+ {
+ BOOST_ASSERT(m_exponent > max_exponent);
+ BOOST_ASSERT(m_exponent <= exponent_nan);
+ BOOST_ASSERT(eval_is_zero(m_data));
+ }
+ }
+};
+
+template <unsigned bits, class Int>
+inline void copy_and_round(cpp_bin_float<bits> &res, Int &arg)
+{
+ // Precondition: exponent of res must have been set before this function is called
+ // as we may need to adjust it based on how many bits in arg are set.
+ using default_ops::eval_msb;
+ using default_ops::eval_lsb;
+ using default_ops::eval_left_shift;
+ using default_ops::eval_bit_test;
+ using default_ops::eval_right_shift;
+ using default_ops::eval_increment;
+ using default_ops::eval_get_sign;
+
+ // cancellation may have resulted in arg being all zeros:
+ if(eval_get_sign(arg) == 0)
+ {
+ res.exponent() = cpp_bin_float<bits>::exponent_zero;
+ res.sign() = false;
+ res.bits() = static_cast<limb_type>(0u);
+ return;
+ }
+ unsigned msb = eval_msb(arg);
+ if(bits > msb + 1)
+ {
+ // Must have had cancellation in subtraction, shift left and copy:
+ eval_left_shift(arg, bits - msb - 1);
+ res.exponent() -= bits - msb - 1;
+ }
+ else if(bits < msb + 1)
+ {
+ // We have more bits than we need, so round as required,
+ // first get the rounding bit:
+ bool roundup = eval_bit_test(arg, msb - bits);
+ // Then check for a tie:
+ if(roundup && (msb - bits == eval_lsb(arg)))
+ {
+ // Ties round towards even:
+ if(!eval_bit_test(arg, msb - bits + 1))
+ roundup = false;
+ }
+ // Shift off the bits we don't need:
+ eval_right_shift(arg, msb - bits + 1);
+ res.exponent() += msb - bits + 1;
+ if(roundup)
+ {
+ eval_increment(arg);
+ if(eval_bit_test(arg, bits))
+ {
+ // This happens very very rairly:
+ eval_right_shift(arg, 1u);
+ ++res.exponent();
+ }
+ }
+ }
+ BOOST_ASSERT(eval_msb(arg) == bits - 1);
+ res.bits() = arg;
+
+ if(res.exponent() > cpp_bin_float<bits>::max_exponent)
+ {
+ // Overflow:
+ res.exponent() = cpp_bin_float<bits>::exponent_infinity;
+ res.bits() = static_cast<limb_type>(0u);
+ }
+ else if(res.exponent() < cpp_bin_float<bits>::min_exponent)
+ {
+ // Underflow:
+ res.exponent() = cpp_bin_float<bits>::exponent_zero;
+ res.bits() = static_cast<limb_type>(0u);
+ res.sign() = false;
+ }
+}
+
+template <unsigned bits>
+inline void do_eval_add(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg)
+{
+ using default_ops::eval_add;
+ using default_ops::eval_bit_test;
+
+ typename cpp_bin_float<bits>::double_rep_type dt;
+
+ // Special cases first:
+ switch(res.exponent())
+ {
+ case cpp_bin_float<bits>::exponent_zero:
+ res = arg;
+ return;
+ case cpp_bin_float<bits>::exponent_infinity:
+ if(arg.exponent() == cpp_bin_float<bits>::exponent_nan)
+ res = arg;
+ return; // result is still infinite.
+ case cpp_bin_float<bits>::exponent_nan:
+ return; // result is still a NaN.
+ }
+ switch(arg.exponent())
+ {
+ case cpp_bin_float<bits>::exponent_zero:
+ return;
+ case cpp_bin_float<bits>::exponent_infinity:
+ res = arg;
+ return; // result is infinite.
+ case cpp_bin_float<bits>::exponent_nan:
+ res = arg;
+ return; // result is a NaN.
+ }
+
+ int e_diff = res.exponent() - arg.exponent();
+ if(e_diff >= 0)
+ {
+ dt = res.bits();
+ if(e_diff < bits)
+ {
+ eval_left_shift(dt, e_diff);
+ res.exponent() -= e_diff;
+ eval_add(dt, arg.bits());
+ }
+ }
+ else
+ {
+ dt= arg.bits();
+ if(-e_diff < bits)
+ {
+ eval_left_shift(dt, -e_diff);
+ res.exponent() = arg.exponent() + e_diff;
+ eval_add(dt, res.bits());
+ }
+ else
+ res.exponent() = arg.exponent();
+ }
+
+ copy_and_round(res, dt);
+ res.check_invariants();
+}
+
+template <unsigned bits>
+inline void do_eval_subtract(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg)
+{
+ using default_ops::eval_subtract;
+ using default_ops::eval_bit_test;
+
+ typename cpp_bin_float<bits>::double_rep_type dt;
+
+ // Special cases first:
+ switch(res.exponent())
+ {
+ case cpp_bin_float<bits>::exponent_zero:
+ if(arg.exponent() == cpp_bin_float<bits>::exponent_nan)
+ res = std::numeric_limits<number<cpp_bin_float<bits> > >::quiet_NaN().backend();
+ else
+ res = arg;
+ return;
+ case cpp_bin_float<bits>::exponent_infinity:
+ if((arg.exponent() == cpp_bin_float<bits>::exponent_nan) || (arg.exponent() == cpp_bin_float<bits>::exponent_infinity))
+ res = std::numeric_limits<number<cpp_bin_float<bits> > >::quiet_NaN().backend();
+ return;
+ case cpp_bin_float<bits>::exponent_nan:
+ return; // result is still a NaN.
+ }
+ switch(arg.exponent())
+ {
+ case cpp_bin_float<bits>::exponent_zero:
+ return;
+ case cpp_bin_float<bits>::exponent_infinity:
+ res.exponent() = cpp_bin_float<bits>::exponent_nan;
+ res.sign() = false;
+ res.bits() = static_cast<limb_type>(0u);
+ return; // result is a NaN.
+ case cpp_bin_float<bits>::exponent_nan:
+ res = arg;
+ return; // result is still a NaN.
+ }
+
+ int e_diff = res.exponent() - arg.exponent();
+ if((e_diff > 0) || ((e_diff == 0) && res.bits().compare(arg.bits()) >= 0))
+ {
+ dt = res.bits();
+ if(e_diff < bits)
+ {
+ eval_left_shift(dt, e_diff);
+ res.exponent() -= e_diff;
+ eval_subtract(dt, arg.bits());
+ }
+ }
+ else
+ {
+ dt = arg.bits();
+ if(-e_diff < bits)
+ {
+ eval_left_shift(dt, -e_diff);
+ res.exponent() = arg.exponent() + e_diff;
+ eval_subtract(dt, res.bits());
+ res.negate();
+ }
+ else
+ res.exponent() = arg.exponent();
+ }
+
+ copy_and_round(res, dt);
+ res.check_invariants();
+}
+
+template <unsigned bits>
+inline void eval_add(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg)
+{
+ if(res.sign() == arg.sign())
+ do_eval_add(res, arg);
+ else
+ do_eval_subtract(res, arg);
+}
+
+template <unsigned bits>
+inline void eval_subtract(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg)
+{
+ if(res.sign() != arg.sign())
+ do_eval_add(res, arg);
+ else
+ do_eval_subtract(res, arg);
+}
+
+template <unsigned bits>
+inline void eval_multiply(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg)
+{
+ using default_ops::eval_bit_test;
+ using default_ops::eval_multiply;
+
+ // Special cases first:
+ switch(res.exponent())
+ {
+ case cpp_bin_float<bits>::exponent_zero:
+ if(arg.exponent() == cpp_bin_float<bits>::exponent_nan)
+ res = arg;
+ return;
+ case cpp_bin_float<bits>::exponent_infinity:
+ switch(arg.exponent())
+ {
+ case cpp_bin_float<bits>::exponent_zero:
+ res = std::numeric_limits<number<cpp_bin_float<bits> > >::quiet_NaN().backend();
+ break;
+ case cpp_bin_float<bits>::exponent_nan:
+ res = arg;
+ break;
+ }
+ return;
+ case cpp_bin_float<bits>::exponent_nan:
+ return;
+ }
+ if(arg.exponent() > cpp_bin_float<bits>::max_exponent)
+ {
+ res = arg;
+ return;
+ }
+ if((res.exponent() > 0) && (arg.exponent() > 0))
+ {
+ if(cpp_bin_float<bits>::max_exponent + 2 - res.exponent() < arg.exponent())
+ {
+ // We will certainly overflow:
+ res.exponent() = cpp_bin_float<bits>::exponent_infinity;
+ res.sign() = res.sign() != arg.sign();
+ res.bits() = static_cast<limb_type>(0u);
+ return;
+ }
+ }
+ if((res.exponent() < 0) && (arg.exponent() < 0))
+ {
+ if(cpp_bin_float<bits>::min_exponent - 2 - res.exponent() > arg.exponent())
+ {
+ // We will certainly underflow:
+ res.exponent() = cpp_bin_float<bits>::exponent_zero;
+ res.sign() = false;
+ res.bits() = static_cast<limb_type>(0u);
+ return;
+ }
+ }
+
+ typename cpp_bin_float<bits>::double_rep_type dt;
+ eval_multiply(dt, res.bits(), arg.bits());
+ res.exponent() += arg.exponent() - bits + 1;
+ copy_and_round(res, dt);
+ res.check_invariants();
+ res.sign() = res.sign() != arg.sign();
+}
+
+template <unsigned bits>
+inline void eval_divide(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &u, const cpp_bin_float<bits> &v)
+{
+ using default_ops::eval_subtract;
+ using default_ops::eval_qr;
+ using default_ops::eval_bit_test;
+ using default_ops::eval_get_sign;
+
+ //
+ // Special cases first:
+ //
+ switch(u.exponent())
+ {
+ case cpp_bin_float<bits>::exponent_zero:
+ switch(v.exponent())
+ {
+ case cpp_bin_float<bits>::exponent_zero:
+ case cpp_bin_float<bits>::exponent_nan:
+ res = std::numeric_limits<number<cpp_bin_float<bits> > >::quiet_NaN().backend();
+ return;
+ }
+ res = u;
+ return;
+ case cpp_bin_float<bits>::exponent_infinity:
+ switch(v.exponent())
+ {
+ case cpp_bin_float<bits>::exponent_infinity:
+ case cpp_bin_float<bits>::exponent_nan:
+ res = std::numeric_limits<number<cpp_bin_float<bits> > >::quiet_NaN().backend();
+ return;
+ }
+ res = u;
+ return;
+ case cpp_bin_float<bits>::exponent_nan:
+ res = std::numeric_limits<number<cpp_bin_float<bits> > >::quiet_NaN().backend();
+ return;
+ }
+ switch(v.exponent())
+ {
+ case cpp_bin_float<bits>::exponent_zero:
+ {
+ bool s = u.sign() != v.sign();
+ res = std::numeric_limits<number<cpp_bin_float<bits> > >::infinity().backend();
+ res.sign() = s;
+ return;
+ }
+ case cpp_bin_float<bits>::exponent_infinity:
+ res.exponent() = cpp_bin_float<bits>::exponent_zero;
+ res.bits() = limb_type(0);
+ res.sign() = false;
+ return;
+ case cpp_bin_float<bits>::exponent_nan:
+ res = std::numeric_limits<number<cpp_bin_float<bits> > >::quiet_NaN().backend();
+ return;
+ }
+
+ // We can scale u and v so that both are integers, then perform integer
+ // division to obtain quotient q and remainder r, such that:
+ //
+ // q * v + r = u
+ //
+ // and hense:
+ //
+ // q + r/v = u/v
+ //
+ // From this, assuming q has "bits" bits, we only need to determine whether
+ // r/v is less than, equal to, or greater than 0.5 to determine rounding -
+ // this we can do with a shift and comparison.
+ //
+ // We can set the exponent and sign of the result up front:
+ //
+ res.exponent() = u.exponent() - v.exponent() - 1;
+ res.sign() = u.sign() != v.sign();
+ //
+ // Now get the quotient and remainder:
+ //
+ typename cpp_bin_float<bits>::double_rep_type t(u.bits()), t2(v.bits()), q, r;
+ eval_left_shift(t, bits);
+ eval_qr(t, t2, q, r);
+ //
+ // We now have either "bits" or "bits+1" significant bits in q.
+ //
+ static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
+ if(eval_bit_test(q, bits))
+ {
+ //
+ // OK we have bits+1 bits, so we already have rounding info,
+ // we just need to changes things if the last bit is 1 and the
+ // remainder is non-zero (ie we do not have a tie).
+ //
+ BOOST_ASSERT(eval_msb(q) == bits);
+ if((q.limbs()[0] & 1u) && eval_get_sign(r))
+ {
+ eval_left_shift(q, limb_bits);
+ q.limbs()[0] = 1;
+ res.exponent() -= limb_bits;
+ }
+ }
+ else
+ {
+ //
+ // We have exactly "bits" bits in q.
+ // Get rounding info, which we can get by comparing 2r with v.
+ // We want to call copy_and_round to handle rounding and general cleanup,
+ // so we'll left shift q and add some fake bits on the end to represent
+ // how we'll be rounding.
+ //
+ BOOST_ASSERT(eval_msb(q) == bits - 1);
+ eval_left_shift(q, limb_bits);
+ res.exponent() -= limb_bits;
+ eval_left_shift(r, 1u);
+ int c = r.compare(v.bits());
+ if(c == 0)
+ q.limbs()[0] = static_cast<limb_type>(1u) << (limb_bits - 1);
+ else if(c > 0)
+ q.limbs()[0] = (static_cast<limb_type>(1u) << (limb_bits - 1)) + static_cast<limb_type>(1u);
+ }
+ copy_and_round(res, q);
+}
+
+template <unsigned bits>
+inline void eval_divide(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg)
+{
+ eval_divide(res, res, arg);
+}
+
+template <unsigned bits>
+inline void eval_convert_to(long long *res, const cpp_bin_float<bits> &arg)
+{
+ typename cpp_bin_float<bits>::rep_type man(arg.bits());
+ int shift = bits - 1 - arg.exponent();
+ if(shift > bits - 1)
+ {
+ *res = 0;
+ return;
+ }
+ else if(shift < 0)
+ {
+ // TODO: what if we have fewer bits than a long long?
+ *res = (std::numeric_limits<long long>::max)();
+ return;
+ }
+ eval_right_shift(man, shift);
+ eval_convert_to(res, man);
+ if(arg.sign())
+ *res = -*res;
+}
+
+template <unsigned bits>
+inline void eval_convert_to(unsigned long long *res, const cpp_bin_float<bits> &arg)
+{
+ typename cpp_bin_float<bits>::rep_type man(arg.bits());
+ int shift = bits - 1 - arg.exponent();
+ if(shift > bits - 1)
+ {
+ *res = 0;
+ return;
+ }
+ else if(shift < 0)
+ {
+ // TODO: what if we have fewer bits than a long long?
+ *res = (std::numeric_limits<long long>::max)();
+ return;
+ }
+ eval_right_shift(man, shift);
+ eval_convert_to(res, man);
+}
+
+template <unsigned bits>
+inline void eval_convert_to(long double *res, const cpp_bin_float<bits> &arg)
+{
+ int e = arg.exponent();
+ e -= bits - 1;
+ eval_convert_to(res, arg.bits());
+ *res = std::ldexp(*res, e);
+ if(arg.sign())
+ *res = -*res;
+}
+
+template <unsigned bits>
+inline void eval_frexp(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg, int *e)
+{
+ res = arg;
+ *e = arg.exponent() + 1;
+ res.exponent() = -1;
+}
+
+template <unsigned bits>
+inline void eval_ldexp(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg, int e)
+{
+ res = arg;
+ res.exponent() += e;
+}
+
+/*
+* Sign manipulation
+*/
+
+template <unsigned bits>
+inline void eval_abs(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg)
+{
+ res = arg;
+ res.sign() = false;
+}
+
+template <unsigned bits>
+inline void eval_fabs(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg)
+{
+ res = arg;
+ res.sign() = false;
+}
+
+template <unsigned bits>
+inline int eval_fpclassify(const cpp_bin_float<bits> &arg)
+{
+ switch(arg.exponent())
+ {
+ case cpp_bin_float<bits>::exponent_zero:
+ return FP_ZERO;
+ case cpp_bin_float<bits>::exponent_infinity:
+ return FP_INFINITE;
+ case cpp_bin_float<bits>::exponent_nan:
+ return FP_NAN;
+ }
+ return FP_NORMAL;
+}
+
+template <unsigned bits>
+inline void eval_sqrt(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg)
+{
+ using default_ops::eval_integer_sqrt;
+ if(arg.exponent() > cpp_bin_float<bits>::max_exponent)
+ {
+ res = arg;
+ return;
+ }
+ if(arg.sign())
+ {
+ res = std::numeric_limits<number<cpp_bin_float<bits> > >::quiet_NaN().backend();
+ return;
+ }
+
+ typename cpp_bin_float<bits>::double_rep_type t(arg.bits()), r, s;
+ eval_left_shift(t, arg.exponent() & 1 ? bits : bits - 1);
+ eval_integer_sqrt(s, r, t);
+
+ if(!eval_bit_test(s, bits))
+ {
+ // We have exactly the right number of bits in the result, round as required:
+ if(s.compare(r) < 0)
+ {
+ eval_increment(s);
+ }
+ }
+ int ae = arg.exponent();
+ res.exponent() = ae / 2;
+ if((ae & 1) && (ae < 0))
+ --res.exponent();
+ copy_and_round(res, s);
+}
+
+template <unsigned bits>
+inline void eval_floor(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg)
+{
+ using default_ops::eval_increment;
+ int shift = (int)bits - arg.exponent() - 1;
+ if((arg.exponent() > cpp_bin_float<bits>::max_exponent) || (shift <= 0))
+ {
+ // Either arg is already an integer, or a special value:
+ res = arg;
+ return;
+ }
+ if(shift >= bits)
+ {
+ res = arg.sign() ? -1 : 0;
+ return;
+ }
+ bool fractional = 1 + (int)eval_lsb(arg.bits()) < shift;
+ res = arg;
+ eval_right_shift(res.bits(), shift);
+ if(fractional && res.sign())
+ {
+ eval_increment(res.bits());
+ if(eval_msb(res.bits()) != bits - 1 - shift)
+ {
+ // Must have extended result by one bit in the increment:
+ --shift;
+ ++res.exponent();
+ }
+ }
+ eval_left_shift(res.bits(), shift);
+}
+
+template <unsigned bits>
+inline void eval_ceil(cpp_bin_float<bits> &res, const cpp_bin_float<bits> &arg)
+{
+ using default_ops::eval_increment;
+ int shift = (int)bits - arg.exponent() - 1;
+ if((arg.exponent() > cpp_bin_float<bits>::max_exponent) || (shift <= 0))
+ {
+ // Either arg is already an integer, or a special value:
+ res = arg;
+ return;
+ }
+ if(shift >= bits)
+ {
+ res = arg.sign() ? 0 : 1;
+ return;
+ }
+ bool fractional = 1 + (int)eval_lsb(arg.bits()) < shift;
+ res = arg;
+ eval_right_shift(res.bits(), shift);
+ if(fractional && !res.sign())
+ {
+ eval_increment(res.bits());
+ if(eval_msb(res.bits()) != bits - 1 - shift)
+ {
+ // Must have extended result by one bit in the increment:
+ --shift;
+ ++res.exponent();
+ }
+ }
+ eval_left_shift(res.bits(), shift);
+}
+
+} // namespace backends
+
+using backends::cpp_bin_float;
+
+template<unsigned bits>
+struct number_category<cpp_bin_float<bits> > : public boost::mpl::int_<boost::multiprecision::number_kind_floating_point>{};
+
+typedef number<backends::cpp_bin_float<113>, et_off> bin_float128;
+
+}} // namespaces
+
+namespace std{
+
+//
+// numeric_limits [partial] specializations for the types declared in this header:
+//
+template<unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+class numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >
+{
+ typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> number_type;
+public:
+ BOOST_STATIC_CONSTEXPR bool is_specialized = true;
+ static number_type (min)()
+ {
+ initializer.do_nothing();
+ static std::pair<bool, number_type> value;
+ if(!value.first)
+ {
+ value.first = true;
+ value.second = 1u;
+ value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<bits>::min_exponent;
+ }
+ return value.second;
+ }
+ static number_type (max)()
+ {
+ initializer.do_nothing();
+ static std::pair<bool, number_type> value;
+ if(!value.first)
+ {
+ value.first = true;
+ eval_complement(value.second.backend().bits(), value.second.backend().bits());
+ value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<bits>::max_exponent;
+ }
+ return value.second;
+ }
+ BOOST_STATIC_CONSTEXPR number_type lowest()
+ {
+ return -(max)();
+ }
+ BOOST_STATIC_CONSTEXPR int digits = bits;
+ BOOST_STATIC_CONSTEXPR int digits10 = bits * 301 / 1000;
+ // Is this really correct???
+ BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2;
+ BOOST_STATIC_CONSTEXPR bool is_signed = true;
+ BOOST_STATIC_CONSTEXPR bool is_integer = false;
+ BOOST_STATIC_CONSTEXPR bool is_exact = false;
+ BOOST_STATIC_CONSTEXPR int radix = 2;
+ static number_type epsilon()
+ {
+ initializer.do_nothing();
+ static std::pair<bool, number_type> value;
+ if(!value.first)
+ {
+ value.first = true;
+ value.second = 1;
+ value.second = ldexp(value.second, 1 - (int)bits);
+ }
+ return value.second;
+ }
+ // What value should this be????
+ static number_type round_error()
+ {
+ // returns epsilon/2
+ initializer.do_nothing();
+ static std::pair<bool, number_type> value;
+ if(!value.first)
+ {
+ value.first = true;
+ value.second = 1;
+ value.second = ldexp(value.second, -(int)bits);
+ }
+ return value.second;
+ }
+ BOOST_STATIC_CONSTEXPR long min_exponent = boost::multiprecision::cpp_bin_float<bits>::min_exponent;
+ BOOST_STATIC_CONSTEXPR long min_exponent10 = (min_exponent / 1000) * 301L;
+ BOOST_STATIC_CONSTEXPR long max_exponent = boost::multiprecision::cpp_bin_float<bits>::max_exponent;
+ BOOST_STATIC_CONSTEXPR long max_exponent10 = (max_exponent / 1000) * 301L;
+ BOOST_STATIC_CONSTEXPR bool has_infinity = true;
+ BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
+ BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
+ BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
+ BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
+ static number_type infinity()
+ {
+ // returns epsilon/2
+ initializer.do_nothing();
+ static std::pair<bool, number_type> value;
+ if(!value.first)
+ {
+ value.first = true;
+ value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<bits>::exponent_infinity;
+ }
+ return value.second;
+ }
+ static number_type quiet_NaN()
+ {
+ return number_type();
+ }
+ BOOST_STATIC_CONSTEXPR number_type signaling_NaN()
+ {
+ return number_type(0);
+ }
+ BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(0); }
+ BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
+ BOOST_STATIC_CONSTEXPR bool is_bounded = true;
+ BOOST_STATIC_CONSTEXPR bool is_modulo = false;
+ BOOST_STATIC_CONSTEXPR bool traps = true;
+ BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
+ BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest;
+private:
+ struct data_initializer
+ {
+ data_initializer()
+ {
+ std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits> > >::epsilon();
+ std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits> > >::round_error();
+ (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits> > >::min)();
+ (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits> > >::max)();
+ std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits> > >::infinity();
+ std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits> > >::quiet_NaN();
+ }
+ void do_nothing()const{}
+ };
+ static const data_initializer initializer;
+};
+
+template<unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::data_initializer numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::initializer;
+
+#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
+
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::digits;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::digits10;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::max_digits10;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::is_signed;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::is_integer;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::is_exact;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::radix;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::min_exponent;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::min_exponent10;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::max_exponent;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::max_exponent10;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::has_infinity;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::has_quiet_NaN;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::has_signaling_NaN;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::has_denorm;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::has_denorm_loss;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::is_iec559;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::is_bounded;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::is_modulo;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::traps;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::tinyness_before;
+template <unsigned bits, boost::multiprecision::expression_template_option ExpressionTemplates>
+BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<bits>, ExpressionTemplates> >::round_style;
+
+#endif
+
+} // namespace std
+
+#endif
Added: sandbox/multiprecision.cpp_bin_float/libs/multiprecision/test/test_arithmetic_cpp_bin_float_1.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ sandbox/multiprecision.cpp_bin_float/libs/multiprecision/test/test_arithmetic_cpp_bin_float_1.cpp 2013-08-08 13:52:19 EDT (Thu, 08 Aug 2013) (r85242)
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////
+// 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_
+
+#ifdef _MSC_VER
+# define _SCL_SECURE_NO_WARNINGS
+#endif
+
+#include <boost/multiprecision/cpp_bin_float.hpp>
+
+#include "libs/multiprecision/test/test_arithmetic.hpp"
+
+template <unsigned D>
+struct related_type<boost::multiprecision::number< boost::multiprecision::cpp_bin_float<D> > >
+{
+ typedef boost::multiprecision::number< boost::multiprecision::cpp_bin_float<D/2> > type;
+};
+
+int main()
+{
+ test<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<256> > >();
+ return boost::report_errors();
+}
+
Added: sandbox/multiprecision.cpp_bin_float/libs/multiprecision/test/test_cpp_bin_float.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ sandbox/multiprecision.cpp_bin_float/libs/multiprecision/test/test_cpp_bin_float.cpp 2013-08-08 13:52:19 EDT (Thu, 08 Aug 2013) (r85242)
@@ -0,0 +1,189 @@
+// Copyright John Maddock 2013.
+
+// Use, modification and distribution are subject to 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)
+
+#ifdef _MSC_VER
+# define _SCL_SECURE_NO_WARNINGS
+#endif
+
+#include <boost/multiprecision/cpp_bin_float.hpp>
+#ifdef TEST_MPFR
+#include <boost/multiprecision/mpfr.hpp>
+#endif
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/random/uniform_int.hpp>
+#include "libs/multiprecision/test/test.hpp"
+#include <iostream>
+#include <iomanip>
+
+template <class T>
+T generate_random()
+{
+ typedef int e_type;
+ static boost::random::mt19937 gen;
+ T val = gen();
+ T prev_val = -1;
+ while(val != prev_val)
+ {
+ val *= (gen.max)();
+ prev_val = val;
+ val += gen();
+ }
+ e_type e;
+ val = frexp(val, &e);
+
+ static boost::random::uniform_int_distribution<e_type> ui(-20, 20);
+ return ldexp(val, ui(gen));
+}
+
+
+using namespace boost::multiprecision;
+#ifdef TEST_MPFR
+typedef number<mpfr_float_backend<15> > good_type;
+#else
+typedef double good_type;
+#endif
+typedef number<cpp_bin_float<std::numeric_limits<good_type>::digits>, et_off> test_type;
+
+void test_special_cases()
+{
+ test_type max_val = (std::numeric_limits<test_type>::max)();
+ test_type min_val = (std::numeric_limits<test_type>::min)();
+ test_type eps = std::numeric_limits<test_type>::epsilon();
+ test_type inf_val = (std::numeric_limits<test_type>::infinity)();
+ test_type nan_val = (std::numeric_limits<test_type>::quiet_NaN)();
+
+ BOOST_CHECK((boost::math::isnormal)(max_val));
+ BOOST_CHECK((boost::math::isnormal)(-max_val));
+ BOOST_CHECK((boost::math::isnormal)(min_val));
+ BOOST_CHECK((boost::math::isnormal)(-min_val));
+ BOOST_CHECK((boost::math::isinf)(inf_val));
+ BOOST_CHECK((boost::math::isinf)(-inf_val));
+ BOOST_CHECK((boost::math::isnan)(nan_val));
+ BOOST_CHECK((boost::math::isnan)(-nan_val));
+
+ if(std::numeric_limits<test_type>::has_denorm)
+ min_val = std::numeric_limits<test_type>::denorm_min();
+
+ BOOST_CHECK(test_type(1) + eps != test_type(1));
+ BOOST_CHECK(test_type(1) + eps / 2 == test_type(1));
+
+ // Overflow:
+ BOOST_CHECK_EQUAL(max_val + max_val * eps, inf_val);
+ BOOST_CHECK_EQUAL(-max_val - max_val * eps, -inf_val);
+ BOOST_CHECK_EQUAL(max_val * 2, inf_val);
+ BOOST_CHECK_EQUAL(max_val * -2, -inf_val);
+ BOOST_CHECK_EQUAL(max_val / 0.5, inf_val);
+ BOOST_CHECK_EQUAL(max_val / -0.5, -inf_val);
+ // Underflow:
+ BOOST_CHECK_EQUAL(min_val * 2 - 1.5 * min_val, 0);
+ BOOST_CHECK_EQUAL(-min_val * 2 + 1.5 * min_val, 0);
+ BOOST_CHECK_EQUAL(min_val / 2, 0);
+ BOOST_CHECK_EQUAL(min_val * 0.5, 0);
+ BOOST_CHECK_EQUAL(min_val - min_val, 0);
+ BOOST_CHECK_EQUAL(max_val - max_val, 0);
+ BOOST_CHECK_EQUAL(-min_val + min_val, 0);
+ BOOST_CHECK_EQUAL(-max_val + max_val, 0);
+ // Things involving zero:
+ BOOST_CHECK_EQUAL(max_val + 0, max_val);
+ BOOST_CHECK_EQUAL(max_val - 0, max_val);
+ BOOST_CHECK_EQUAL(0 + max_val, max_val);
+ BOOST_CHECK_EQUAL(0 - max_val, -max_val);
+ BOOST_CHECK_EQUAL(max_val * 0, 0);
+ BOOST_CHECK_EQUAL(0 * max_val, 0);
+ BOOST_CHECK_EQUAL(max_val / 0, inf_val);
+ BOOST_CHECK_EQUAL(0 / max_val, 0);
+ BOOST_CHECK_EQUAL(-max_val / 0, -inf_val);
+ BOOST_CHECK_EQUAL(0 / -max_val, 0);
+ // Things involving infinity:
+ BOOST_CHECK_EQUAL(inf_val + 2, inf_val);
+ BOOST_CHECK_EQUAL(inf_val + inf_val, inf_val);
+ BOOST_CHECK_EQUAL(-inf_val - 2, -inf_val);
+ BOOST_CHECK_EQUAL(inf_val - 2, inf_val);
+ BOOST_CHECK_EQUAL(-inf_val + 2, -inf_val);
+ BOOST_CHECK((boost::math::isnan)(inf_val - inf_val));
+ BOOST_CHECK_EQUAL(inf_val * 2, inf_val);
+ BOOST_CHECK_EQUAL(-inf_val * 2, -inf_val);
+ BOOST_CHECK((boost::math::isnan)(inf_val * 0));
+ BOOST_CHECK((boost::math::isnan)(-inf_val * 0));
+ BOOST_CHECK_EQUAL(inf_val / 2, inf_val);
+ BOOST_CHECK_EQUAL(-inf_val / 2, -inf_val);
+ BOOST_CHECK_EQUAL(inf_val / 0, inf_val);
+ BOOST_CHECK_EQUAL(-inf_val / 0, -inf_val);
+ BOOST_CHECK((boost::math::isnan)(inf_val / inf_val));
+ BOOST_CHECK((boost::math::isnan)(-inf_val / inf_val));
+ // Things involving nan:
+ BOOST_CHECK((boost::math::isnan)(nan_val + 2));
+ BOOST_CHECK((boost::math::isnan)(nan_val - 2));
+ BOOST_CHECK((boost::math::isnan)(nan_val + 0));
+ BOOST_CHECK((boost::math::isnan)(nan_val - 0));
+ BOOST_CHECK((boost::math::isnan)(nan_val + inf_val));
+ BOOST_CHECK((boost::math::isnan)(nan_val - inf_val));
+ BOOST_CHECK((boost::math::isnan)(nan_val + nan_val));
+ BOOST_CHECK((boost::math::isnan)(nan_val - nan_val));
+ BOOST_CHECK((boost::math::isnan)(2 + nan_val));
+ BOOST_CHECK((boost::math::isnan)(2 - nan_val));
+ BOOST_CHECK((boost::math::isnan)(0 - nan_val));
+ BOOST_CHECK((boost::math::isnan)(0 - nan_val));
+ BOOST_CHECK((boost::math::isnan)(inf_val + nan_val));
+ BOOST_CHECK((boost::math::isnan)(inf_val - nan_val));
+ BOOST_CHECK((boost::math::isnan)(nan_val * 2));
+ BOOST_CHECK((boost::math::isnan)(nan_val / 2));
+ BOOST_CHECK((boost::math::isnan)(nan_val * 0));
+ BOOST_CHECK((boost::math::isnan)(nan_val / 0));
+ BOOST_CHECK((boost::math::isnan)(nan_val * inf_val));
+ BOOST_CHECK((boost::math::isnan)(nan_val / inf_val));
+ BOOST_CHECK((boost::math::isnan)(nan_val * nan_val));
+ BOOST_CHECK((boost::math::isnan)(nan_val / nan_val));
+ BOOST_CHECK((boost::math::isnan)(2 * nan_val));
+ BOOST_CHECK((boost::math::isnan)(2 / nan_val));
+ BOOST_CHECK((boost::math::isnan)(0 / nan_val));
+ BOOST_CHECK((boost::math::isnan)(0 / nan_val));
+ BOOST_CHECK((boost::math::isnan)(inf_val * nan_val));
+ BOOST_CHECK((boost::math::isnan)(inf_val / nan_val));
+}
+
+int main()
+{
+ test_special_cases();
+
+ for(unsigned i = 0; i < 100000; ++i)
+ {
+ good_type a = generate_random<good_type>();
+ good_type b = generate_random<good_type>();
+ test_type ta(a);
+ test_type tb(b);
+
+ BOOST_CHECK_EQUAL(test_type(a * b), ta * tb);
+ BOOST_CHECK_EQUAL(test_type(-a * b), -ta * tb);
+ BOOST_CHECK_EQUAL(test_type(a * -b), ta * -tb);
+ BOOST_CHECK_EQUAL(test_type(-a * -b), -ta * -tb);
+
+ BOOST_CHECK_EQUAL(test_type(a + b), ta + tb);
+ BOOST_CHECK_EQUAL(test_type(-a + b), -ta + tb);
+ BOOST_CHECK_EQUAL(test_type(a + -b), ta + -tb);
+ BOOST_CHECK_EQUAL(test_type(-a + -b), -ta + -tb);
+
+ BOOST_CHECK_EQUAL(test_type(a - b), ta - tb);
+ BOOST_CHECK_EQUAL(test_type(-a - b), -ta - tb);
+ BOOST_CHECK_EQUAL(test_type(a - -b), ta - -tb);
+ BOOST_CHECK_EQUAL(test_type(-a - -b), -ta - -tb);
+
+ BOOST_CHECK_EQUAL(test_type(a / b), ta / tb);
+ BOOST_CHECK_EQUAL(test_type(-a / b), -ta / tb);
+ BOOST_CHECK_EQUAL(test_type(a / -b), ta / -tb);
+ BOOST_CHECK_EQUAL(test_type(-a / -b), -ta / -tb);
+
+ BOOST_CHECK_EQUAL(test_type(sqrt(a)), sqrt(ta));
+ BOOST_CHECK_EQUAL(test_type(floor(a)), floor(ta));
+ BOOST_CHECK_EQUAL(test_type(floor(-a)), floor(-ta));
+ BOOST_CHECK_EQUAL(test_type(ceil(a)), ceil(ta));
+ BOOST_CHECK_EQUAL(test_type(ceil(-a)), ceil(-ta));
+
+ }
+ return boost::report_errors();
+}
+
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk