Skip to content

Commit

Permalink
Fix cpp_bin_float conversions,
Browse files Browse the repository at this point in the history
fix inverse trig logic to get as many digits as possible from std::asin.
Add test case.
Fixes: https://svn.boost.org/trac/boost/ticket/11764
  • Loading branch information
jzmaddock committed Oct 29, 2015
1 parent e28b1be commit 7dfea11
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 6 deletions.
18 changes: 16 additions & 2 deletions include/boost/multiprecision/cpp_bin_float.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class cpp_bin_float

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 boost::mpl::list<float, double, long double> float_types;
typedef Exponent exponent_type;

static const exponent_type max_exponent_limit = boost::integer_traits<exponent_type>::const_max - 2 * static_cast<exponent_type>(bit_count);
Expand Down Expand Up @@ -104,6 +104,18 @@ class cpp_bin_float
this->assign_float(f);
}

template <class Float>
explicit cpp_bin_float(const Float& f,
typename boost::enable_if_c<
(number_category<Float>::value == number_kind_floating_point)
&& (std::numeric_limits<Float>::digits > (int)bit_count)
&& (std::numeric_limits<Float>::radix == 2)
>::type const* = 0)
: m_data(), m_exponent(0), m_sign(false)
{
this->assign_float(f);
}

cpp_bin_float& operator=(const cpp_bin_float &o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<rep_type&>() = std::declval<const rep_type&>()))
{
m_data = o.m_data;
Expand All @@ -125,7 +137,7 @@ class cpp_bin_float
template <class Float>
typename boost::enable_if_c<
(number_category<Float>::value == number_kind_floating_point)
&& (std::numeric_limits<Float>::digits <= (int)bit_count)
//&& (std::numeric_limits<Float>::digits <= (int)bit_count)
&& (std::numeric_limits<Float>::radix == 2), cpp_bin_float&>::type operator=(const Float& f)
{
return assign_float(f);
Expand Down Expand Up @@ -1405,6 +1417,8 @@ namespace detail{

template<unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2, unsigned D2, backends::digit_base_type B2, class A2, class E2, E2 M3, E2 M4>
struct is_explicitly_convertible<backends::cpp_bin_float<D1, B1, A1, E1, M1, M2>, backends::cpp_bin_float<D2, B2, A2, E2, M3, M4> > : public mpl::true_ {};
template<class FloatT, unsigned D2, backends::digit_base_type B2, class A2, class E2, E2 M3, E2 M4>
struct is_explicitly_convertible<FloatT, backends::cpp_bin_float<D2, B2, A2, E2, M3, M4> > : public boost::is_floating_point<FloatT> {};

}
#endif
Expand Down
6 changes: 3 additions & 3 deletions include/boost/multiprecision/detail/functions/trig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,12 +488,12 @@ void eval_asin(T& result, const T& x)
}

// Get initial estimate using standard math function asin.
double dd;
long double dd;
eval_convert_to(&dd, xx);

result = fp_type(std::asin(dd));
result = (long double)(std::asin(dd));

unsigned current_digits = std::numeric_limits<double>::digits - 5;
unsigned current_digits = std::numeric_limits<long double>::digits - 5;
unsigned target_precision = boost::multiprecision::detail::digits2<number<T, et_on> >::value;

// Newton-Raphson iteration
Expand Down
5 changes: 4 additions & 1 deletion test/Jamfile.v2
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,10 @@ run test_mixed_cpp_bin_float.cpp ;
run test_mixed_cpp_dec_float.cpp ;
run test_mixed_mpf_float.cpp gmp : : : [ check-target-builds ../config//has_gmp : : <build>no ] ;
run test_mixed_mpfr_float.cpp mpfr gmp : : : [ check-target-builds ../config//has_mpfr : : <build>no ] ;

#
# Check for narrowing conversions:
#
run test_float_conversions.cpp ;

if $(enable-specfun)
{
Expand Down
40 changes: 40 additions & 0 deletions test/test_float_conversions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
///////////////////////////////////////////////////////////////
// Copyright 2015 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/detail/lightweight_test.hpp>
#include <boost/array.hpp>
#include "test.hpp"

#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/math/constants/constants.hpp>

int main()
{
using namespace boost::multiprecision;

BOOST_STATIC_ASSERT(boost::is_convertible<float, cpp_bin_float_single>::value);
BOOST_STATIC_ASSERT(!boost::is_convertible<double, cpp_bin_float_single>::value);
BOOST_STATIC_ASSERT(!boost::is_convertible<long double, cpp_bin_float_single>::value);

cpp_bin_float_single s = boost::math::constants::pi<cpp_bin_float_single>();

typedef number<backends::cpp_bin_float<11, backends::digit_base_2, void, boost::int8_t, -14, 15>, et_off> cpp_bin_float_half;

BOOST_STATIC_ASSERT(!boost::is_convertible<float, cpp_bin_float_half>::value);
BOOST_STATIC_ASSERT(!boost::is_convertible<double, cpp_bin_float_half>::value);
BOOST_STATIC_ASSERT(!boost::is_convertible<long double, cpp_bin_float_half>::value);

cpp_bin_float_half hs = boost::math::constants::pi<cpp_bin_float_half>();

return boost::report_errors();
}



0 comments on commit 7dfea11

Please sign in to comment.