Skip to content

Commit

Permalink
float128.hpp: Update so our code works even when Q literals are not a…
Browse files Browse the repository at this point in the history
…llowed.

See: #83
  • Loading branch information
jzmaddock committed Oct 13, 2018
1 parent ead98ee commit 9a53f1c
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 8 deletions.
89 changes: 81 additions & 8 deletions include/boost/multiprecision/float128.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,77 @@ struct number_category<float128_type> : public mpl::int_<number_kind_floating_po

typedef number<float128_backend, et_off> float128;

#ifndef BOOST_NO_CXX11_CONSTEXPR

namespace quad_constants {
constexpr __float128 quad_min = static_cast<__float128>(1)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN) / 1073741824;

constexpr __float128 quad_denorm_min = static_cast<__float128>(1)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN)
* static_cast<__float128>(DBL_MIN) / 5.5751862996326557854e+42;

constexpr double dbl_mult = 8.9884656743115795386e+307; // This has one bit set only.
constexpr __float128 quad_max = (static_cast<__float128>(1) - 9.62964972193617926527988971292463659e-35) // This now has all bits sets to 1
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult)
* static_cast<__float128>(dbl_mult) * 65536;
}

#define BOOST_MP_QUAD_MIN boost::multiprecision::quad_constants::quad_min
#define BOOST_MP_QUAD_DENORM_MIN boost::multiprecision::quad_constants::quad_denorm_min
#define BOOST_MP_QUAD_MAX boost::multiprecision::quad_constants::quad_max

#else

#define BOOST_MP_QUAD_MIN 3.36210314311209350626267781732175260e-4932Q
#define BOOST_MP_QUAD_DENORM_MIN 6.475175119438025110924438958227646552e-4966Q
#define BOOST_MP_QUAD_MAX 1.18973149535723176508575932662800702e4932Q

#endif

namespace backends{

struct float128_backend
Expand Down Expand Up @@ -157,15 +228,17 @@ struct float128_backend
}
float128_backend(long double const& f)
{
BOOST_STATIC_CONSTEXPR __float128 inf_val = static_cast<__float128>(HUGE_VAL);
if(boost::math::isinf(f))
m_value = (f < 0) ? -1.0Q / 0.0Q : 1.0Q / 0.0Q;
m_value = (f < 0) ? -inf_val : inf_val;
else
m_value = f;
}
float128_backend& operator=(long double const& f)
{
BOOST_STATIC_CONSTEXPR __float128 inf_val = static_cast<__float128>(HUGE_VAL);
if(boost::math::isinf(f))
m_value = (f < 0) ? -1.0Q / 0.0Q : 1.0Q / 0.0Q;
m_value = (f < 0) ? -inf_val : inf_val;
else
m_value = f;
return *this;
Expand Down Expand Up @@ -364,7 +437,7 @@ inline int eval_fpclassify(const float128_backend& arg)
float128_backend t(arg);
if(t.value() < 0)
t.negate();
if(t.value() < 3.36210314311209350626267781732175260e-4932Q)
if(t.value() < BOOST_MP_QUAD_MIN)
return FP_SUBNORMAL;
return FP_NORMAL;
}
Expand Down Expand Up @@ -645,8 +718,8 @@ class numeric_limits<boost::multiprecision::number<boost::multiprecision::backen
typedef boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> number_type;
public:
BOOST_STATIC_CONSTEXPR bool is_specialized = true;
static number_type (min)() BOOST_NOEXCEPT { return 3.36210314311209350626267781732175260e-4932Q; }
static number_type (max)() BOOST_NOEXCEPT { return 1.18973149535723176508575932662800702e4932Q; }
static number_type (min)() BOOST_NOEXCEPT { return BOOST_MP_QUAD_MIN; }
static number_type (max)() BOOST_NOEXCEPT { return BOOST_MP_QUAD_MAX; }
static number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
BOOST_STATIC_CONSTEXPR int digits = 113;
BOOST_STATIC_CONSTEXPR int digits10 = 33;
Expand All @@ -655,7 +728,7 @@ class numeric_limits<boost::multiprecision::number<boost::multiprecision::backen
BOOST_STATIC_CONSTEXPR bool is_integer = false;
BOOST_STATIC_CONSTEXPR bool is_exact = false;
BOOST_STATIC_CONSTEXPR int radix = 2;
static number_type epsilon() { return 1.92592994438723585305597794258492732e-34Q; }
static number_type epsilon() { return 1.92592994438723585305597794258492732e-34; /* this double value has only one bit set and so is exact */ }
static number_type round_error() { return 0.5; }
BOOST_STATIC_CONSTEXPR int min_exponent = -16381;
BOOST_STATIC_CONSTEXPR int min_exponent10 = min_exponent * 301L / 1000L;
Expand All @@ -666,10 +739,10 @@ class numeric_limits<boost::multiprecision::number<boost::multiprecision::backen
BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_present;
BOOST_STATIC_CONSTEXPR bool has_denorm_loss = true;
static number_type infinity() { return 1.0q / 0.0q; }
static number_type infinity() { return HUGE_VAL; /* conversion from double infinity OK */ }
static number_type quiet_NaN() { return number_type("nan"); }
static number_type signaling_NaN() { return 0; }
static number_type denorm_min() { return 6.475175119438025110924438958227646552e-4966Q; }
static number_type denorm_min() { return BOOST_MP_QUAD_DENORM_MIN; }
BOOST_STATIC_CONSTEXPR bool is_iec559 = true;
BOOST_STATIC_CONSTEXPR bool is_bounded = false;
BOOST_STATIC_CONSTEXPR bool is_modulo = false;
Expand Down
12 changes: 12 additions & 0 deletions test/test_convert_from_float128.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,18 @@ void test_convert()

int main()
{
//
// Some basic sanity checks first:
//
BOOST_CHECK_EQUAL(std::numeric_limits<float128>::epsilon(), float128("1.92592994438723585305597794258492732e-34"));
BOOST_CHECK_EQUAL((std::numeric_limits<float128>::min)(), float128("3.36210314311209350626267781732175260e-4932"));
BOOST_CHECK_EQUAL((std::numeric_limits<float128>::max)(), float128("1.18973149535723176508575932662800702e4932"));
BOOST_CHECK_EQUAL((std::numeric_limits<float128>::denorm_min)(), float128("6.475175119438025110924438958227646552e-4966"));
BOOST_CHECK((boost::math::isinf)((std::numeric_limits<float128>::infinity)()));
BOOST_CHECK((std::numeric_limits<float128>::infinity)() > 0);
BOOST_CHECK((boost::math::isnan)((std::numeric_limits<float128>::quiet_NaN)()));


test_convert<float128, cpp_int>();
test_convert<float128, int128_t>();
test_convert<float128, uint128_t>();
Expand Down

0 comments on commit 9a53f1c

Please sign in to comment.