Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Copyright 2011 John Maddock. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_MATH_BIG_NUM_BASE_HPP Chris@16: #define BOOST_MATH_BIG_NUM_BASE_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning(push) Chris@16: # pragma warning(disable:4307) Chris@16: #endif Chris@16: #include Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: #if defined(NDEBUG) && !defined(_DEBUG) Chris@16: # define BOOST_MP_FORCEINLINE BOOST_FORCEINLINE Chris@16: #else Chris@16: # define BOOST_MP_FORCEINLINE inline Chris@16: #endif Chris@16: Chris@16: namespace boost{ namespace multiprecision{ Chris@16: Chris@16: enum expression_template_option Chris@16: { Chris@16: et_off = 0, Chris@16: et_on = 1 Chris@16: }; Chris@16: Chris@16: template Chris@16: struct expression_template_default Chris@16: { Chris@16: static const expression_template_option value = et_on; Chris@16: }; Chris@16: Chris@16: template ::value> Chris@16: class number; Chris@16: Chris@16: template Chris@16: struct is_number : public mpl::false_ {}; Chris@16: Chris@16: template Chris@16: struct is_number > : public mpl::true_ {}; Chris@16: Chris@16: namespace detail{ Chris@16: Chris@16: // Forward-declare an expression wrapper Chris@16: template Chris@16: struct expression; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: template Chris@16: struct is_number_expression : public mpl::false_ {}; Chris@16: Chris@16: template Chris@16: struct is_number_expression > : public mpl::true_ {}; Chris@16: Chris@16: template Chris@16: struct is_compatible_arithmetic_type Chris@16: : public mpl::bool_< Chris@16: is_convertible::value Chris@16: && !is_same::value Chris@16: && !is_number_expression::value> Chris@16: {}; Chris@16: Chris@16: namespace detail{ Chris@16: // Chris@16: // Workaround for missing abs(long long) and abs(__int128) on some compilers: Chris@16: // Chris@16: template Chris@101: BOOST_CONSTEXPR typename enable_if_c<(is_signed::value || is_floating_point::value), T>::type abs(T t) BOOST_NOEXCEPT Chris@16: { Chris@101: // This strange expression avoids a hardware trap in the corner case Chris@101: // that val is the most negative value permitted in long long. Chris@101: // See https://svn.boost.org/trac/boost/ticket/9740. Chris@101: return t < 0 ? T(1u) + T(-(t + 1)) : t; Chris@16: } Chris@16: template Chris@101: BOOST_CONSTEXPR typename enable_if_c<(is_unsigned::value), T>::type abs(T t) BOOST_NOEXCEPT Chris@16: { Chris@16: return t; Chris@16: } Chris@16: Chris@16: #define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs; Chris@16: Chris@101: template Chris@101: BOOST_CONSTEXPR typename enable_if_c<(is_signed::value || is_floating_point::value), typename make_unsigned::type>::type unsigned_abs(T t) BOOST_NOEXCEPT Chris@101: { Chris@101: // This strange expression avoids a hardware trap in the corner case Chris@101: // that val is the most negative value permitted in long long. Chris@101: // See https://svn.boost.org/trac/boost/ticket/9740. Chris@101: return t < 0 ? static_cast::type>(1u) + static_cast::type>(-(t + 1)) : static_cast::type>(t); Chris@101: } Chris@101: template Chris@101: BOOST_CONSTEXPR typename enable_if_c<(is_unsigned::value), T>::type unsigned_abs(T t) BOOST_NOEXCEPT Chris@101: { Chris@101: return t; Chris@101: } Chris@101: Chris@16: // Chris@16: // Move support: Chris@16: // Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: # define BOOST_MP_MOVE(x) std::move(x) Chris@16: #else Chris@16: # define BOOST_MP_MOVE(x) x Chris@16: #endif Chris@16: Chris@16: template Chris@16: struct bits_of Chris@16: { Chris@16: BOOST_STATIC_ASSERT(is_integral::value || is_enum::value || std::numeric_limits::is_specialized); Chris@16: static const unsigned value = Chris@16: std::numeric_limits::is_specialized ? Chris@16: std::numeric_limits::digits Chris@16: : sizeof(T) * CHAR_BIT - (is_signed::value ? 1 : 0); Chris@16: }; Chris@16: Chris@16: template Chris@16: struct has_enough_bits Chris@16: { Chris@16: template Chris@16: struct type : public mpl::bool_::value>= b>{}; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct canonical_imp Chris@16: { Chris@16: typedef typename remove_cv::type>::type type; Chris@16: }; Chris@16: template Chris@16: struct canonical_imp, Backend, Tag> Chris@16: { Chris@16: typedef B type; Chris@16: }; Chris@16: template Chris@16: struct canonical_imp, Backend, Tag> Chris@16: { Chris@16: typedef B type; Chris@16: }; Chris@101: #ifdef __SUNPRO_CC Chris@101: template Chris@101: struct canonical_imp, Backend, mpl::int_<3> > Chris@101: { Chris@101: typedef B type; Chris@101: }; Chris@101: template Chris@101: struct canonical_imp, Backend, mpl::int_<3> > Chris@101: { Chris@101: typedef B type; Chris@101: }; Chris@101: #endif Chris@16: template Chris@16: struct canonical_imp > Chris@16: { Chris@16: typedef typename has_enough_bits::value>::template type pred_type; Chris@16: typedef typename mpl::find_if< Chris@16: typename Backend::signed_types, Chris@16: pred_type Chris@16: >::type iter_type; Chris@16: typedef typename mpl::deref::type type; Chris@16: }; Chris@16: template Chris@16: struct canonical_imp > Chris@16: { Chris@16: typedef typename has_enough_bits::value>::template type pred_type; Chris@16: typedef typename mpl::find_if< Chris@16: typename Backend::unsigned_types, Chris@16: pred_type Chris@16: >::type iter_type; Chris@16: typedef typename mpl::deref::type type; Chris@16: }; Chris@16: template Chris@16: struct canonical_imp > Chris@16: { Chris@16: typedef typename has_enough_bits::value>::template type pred_type; Chris@16: typedef typename mpl::find_if< Chris@16: typename Backend::float_types, Chris@16: pred_type Chris@16: >::type iter_type; Chris@16: typedef typename mpl::deref::type type; Chris@16: }; Chris@16: template Chris@16: struct canonical_imp > Chris@16: { Chris@16: typedef const char* type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct canonical Chris@16: { Chris@16: typedef typename mpl::if_< Chris@16: is_signed, Chris@16: mpl::int_<0>, Chris@16: typename mpl::if_< Chris@16: is_unsigned, Chris@16: mpl::int_<1>, Chris@16: typename mpl::if_< Chris@16: is_floating_point, Chris@16: mpl::int_<2>, Chris@16: typename mpl::if_< Chris@16: mpl::or_< Chris@16: is_convertible, Chris@16: is_same Chris@16: >, Chris@16: mpl::int_<3>, Chris@16: mpl::int_<4> Chris@16: >::type Chris@16: >::type Chris@16: >::type Chris@16: >::type tag_type; Chris@16: Chris@16: typedef typename canonical_imp::type type; Chris@16: }; Chris@16: Chris@16: struct terminal{}; Chris@16: struct negate{}; Chris@16: struct plus{}; Chris@16: struct minus{}; Chris@16: struct multiplies{}; Chris@16: struct divides{}; Chris@16: struct modulus{}; Chris@16: struct shift_left{}; Chris@16: struct shift_right{}; Chris@16: struct bitwise_and{}; Chris@16: struct bitwise_or{}; Chris@16: struct bitwise_xor{}; Chris@16: struct bitwise_complement{}; Chris@16: struct add_immediates{}; Chris@16: struct subtract_immediates{}; Chris@16: struct multiply_immediates{}; Chris@16: struct divide_immediates{}; Chris@16: struct modulus_immediates{}; Chris@16: struct bitwise_and_immediates{}; Chris@16: struct bitwise_or_immediates{}; Chris@16: struct bitwise_xor_immediates{}; Chris@16: struct complement_immediates{}; Chris@16: struct function{}; Chris@16: struct multiply_add{}; Chris@16: struct multiply_subtract{}; Chris@16: Chris@16: template Chris@16: struct backend_type; Chris@16: Chris@16: template Chris@16: struct backend_type > Chris@16: { Chris@16: typedef T type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct backend_type > Chris@16: { Chris@16: typedef typename backend_type::result_type>::type type; Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct combine_expression Chris@16: { Chris@16: #ifdef BOOST_NO_CXX11_DECLTYPE Chris@16: typedef typename mpl::if_c<(sizeof(T1() + T2()) == sizeof(T1)), T1, T2>::type type; Chris@16: #else Chris@16: typedef decltype(T1() + T2()) type; Chris@16: #endif Chris@16: }; Chris@16: Chris@16: template Chris@16: struct combine_expression, T2> Chris@16: { Chris@16: typedef number type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct combine_expression > Chris@16: { Chris@16: typedef number type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct combine_expression, number > Chris@16: { Chris@16: typedef number type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct combine_expression, number > Chris@16: { Chris@16: typedef typename mpl::if_c< Chris@16: is_convertible, number >::value, Chris@16: number, Chris@16: number Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct arg_type Chris@16: { Chris@16: typedef expression type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct arg_type > Chris@16: { Chris@16: typedef expression type; Chris@16: }; Chris@16: Chris@16: struct unmentionable Chris@16: { Chris@16: unmentionable* proc(){ return 0; } Chris@16: }; Chris@16: Chris@16: typedef unmentionable* (unmentionable::*unmentionable_type)(); Chris@16: Chris@16: template Chris@16: struct expression_storage Chris@16: { Chris@16: typedef const T& type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct expression_storage Chris@16: { Chris@16: typedef T* type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct expression_storage Chris@16: { Chris@16: typedef const T* type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct expression_storage > Chris@16: { Chris@16: typedef expression type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct expression Chris@16: { Chris@16: typedef mpl::int_<1> arity; Chris@16: typedef typename arg_type::type left_type; Chris@16: typedef typename left_type::result_type left_result_type; Chris@16: typedef typename left_type::result_type result_type; Chris@16: typedef tag tag_type; Chris@16: Chris@16: explicit expression(const Arg1& a) : arg(a) {} Chris@16: Chris@16: left_type left()const { return left_type(arg); } Chris@16: Chris@16: const Arg1& left_ref()const BOOST_NOEXCEPT { return arg; } Chris@16: Chris@16: static const unsigned depth = left_type::depth + 1; Chris@16: #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS Chris@16: explicit operator bool()const Chris@16: { Chris@16: result_type r(*this); Chris@16: return static_cast(r); Chris@16: } Chris@16: #else Chris@16: operator unmentionable_type()const Chris@16: { Chris@16: result_type r(*this); Chris@16: return r ? &unmentionable::proc : 0; Chris@16: } Chris@16: #endif Chris@16: Chris@16: private: Chris@16: typename expression_storage::type arg; Chris@16: expression& operator=(const expression&); Chris@16: }; Chris@16: Chris@16: template Chris@16: struct expression Chris@16: { Chris@16: typedef mpl::int_<0> arity; Chris@16: typedef Arg1 result_type; Chris@16: typedef terminal tag_type; Chris@16: Chris@16: explicit expression(const Arg1& a) : arg(a) {} Chris@16: Chris@16: const Arg1& value()const BOOST_NOEXCEPT { return arg; } Chris@16: Chris@16: static const unsigned depth = 0; Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS Chris@16: explicit operator bool()const Chris@16: { Chris@16: return static_cast(arg); Chris@16: } Chris@16: #else Chris@16: operator unmentionable_type()const Chris@16: { Chris@16: return arg ? &unmentionable::proc : 0; Chris@16: } Chris@16: #endif Chris@16: Chris@16: private: Chris@16: typename expression_storage::type arg; Chris@16: expression& operator=(const expression&); Chris@16: }; Chris@16: Chris@16: template Chris@16: struct expression Chris@16: { Chris@16: typedef mpl::int_<2> arity; Chris@16: typedef typename arg_type::type left_type; Chris@16: typedef typename arg_type::type right_type; Chris@16: typedef typename left_type::result_type left_result_type; Chris@16: typedef typename right_type::result_type right_result_type; Chris@16: typedef typename combine_expression::type result_type; Chris@16: typedef tag tag_type; Chris@16: Chris@16: expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {} Chris@16: Chris@16: left_type left()const { return left_type(arg1); } Chris@16: right_type right()const { return right_type(arg2); } Chris@16: const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; } Chris@16: const Arg2& right_ref()const BOOST_NOEXCEPT { return arg2; } Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS Chris@16: explicit operator bool()const Chris@16: { Chris@16: result_type r(*this); Chris@16: return static_cast(r); Chris@16: } Chris@16: #else Chris@16: operator unmentionable_type()const Chris@16: { Chris@16: result_type r(*this); Chris@16: return r ? &unmentionable::proc : 0; Chris@16: } Chris@16: #endif Chris@16: static const unsigned left_depth = left_type::depth + 1; Chris@16: static const unsigned right_depth = right_type::depth + 1; Chris@16: static const unsigned depth = left_depth > right_depth ? left_depth : right_depth; Chris@16: private: Chris@16: typename expression_storage::type arg1; Chris@16: typename expression_storage::type arg2; Chris@16: expression& operator=(const expression&); Chris@16: }; Chris@16: Chris@16: template Chris@16: struct expression Chris@16: { Chris@16: typedef mpl::int_<3> arity; Chris@16: typedef typename arg_type::type left_type; Chris@16: typedef typename arg_type::type middle_type; Chris@16: typedef typename arg_type::type right_type; Chris@16: typedef typename left_type::result_type left_result_type; Chris@16: typedef typename middle_type::result_type middle_result_type; Chris@16: typedef typename right_type::result_type right_result_type; Chris@16: typedef typename combine_expression< Chris@16: left_result_type, Chris@16: typename combine_expression::type Chris@16: >::type result_type; Chris@16: typedef tag tag_type; Chris@16: Chris@16: expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {} Chris@16: Chris@16: left_type left()const { return left_type(arg1); } Chris@16: middle_type middle()const { return middle_type(arg2); } Chris@16: right_type right()const { return right_type(arg3); } Chris@16: const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; } Chris@16: const Arg2& middle_ref()const BOOST_NOEXCEPT { return arg2; } Chris@16: const Arg3& right_ref()const BOOST_NOEXCEPT { return arg3; } Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS Chris@16: explicit operator bool()const Chris@16: { Chris@16: result_type r(*this); Chris@16: return static_cast(r); Chris@16: } Chris@16: #else Chris@16: operator unmentionable_type()const Chris@16: { Chris@16: result_type r(*this); Chris@16: return r ? &unmentionable::proc : 0; Chris@16: } Chris@16: #endif Chris@16: static const unsigned left_depth = left_type::depth + 1; Chris@16: static const unsigned middle_depth = middle_type::depth + 1; Chris@16: static const unsigned right_depth = right_type::depth + 1; Chris@16: static const unsigned depth = left_depth > right_depth ? (left_depth > middle_depth ? left_depth : middle_depth) : (right_depth > middle_depth ? right_depth : middle_depth); Chris@16: private: Chris@16: typename expression_storage::type arg1; Chris@16: typename expression_storage::type arg2; Chris@16: typename expression_storage::type arg3; Chris@16: expression& operator=(const expression&); Chris@16: }; Chris@16: Chris@16: template Chris@16: struct expression Chris@16: { Chris@16: typedef mpl::int_<4> arity; Chris@16: typedef typename arg_type::type left_type; Chris@16: typedef typename arg_type::type left_middle_type; Chris@16: typedef typename arg_type::type right_middle_type; Chris@16: typedef typename arg_type::type right_type; Chris@16: typedef typename left_type::result_type left_result_type; Chris@16: typedef typename left_middle_type::result_type left_middle_result_type; Chris@16: typedef typename right_middle_type::result_type right_middle_result_type; Chris@16: typedef typename right_type::result_type right_result_type; Chris@16: typedef typename combine_expression< Chris@16: typename combine_expression< Chris@16: typename combine_expression::type, Chris@16: right_middle_result_type Chris@16: >::type, Chris@16: right_result_type Chris@16: >::type result_type; Chris@16: typedef tag tag_type; Chris@16: Chris@16: expression(const Arg1& a1, const Arg2& a2, const Arg3& a3, const Arg4& a4) : arg1(a1), arg2(a2), arg3(a3), arg4(a4) {} Chris@16: Chris@16: left_type left()const { return left_type(arg1); } Chris@16: left_middle_type left_middle()const { return left_middle_type(arg2); } Chris@16: right_middle_type right_middle()const { return right_middle_type(arg3); } Chris@16: right_type right()const { return right_type(arg4); } Chris@16: const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; } Chris@16: const Arg2& left_middle_ref()const BOOST_NOEXCEPT { return arg2; } Chris@16: const Arg3& right_middle_ref()const BOOST_NOEXCEPT { return arg3; } Chris@16: const Arg4& right_ref()const BOOST_NOEXCEPT { return arg4; } Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS Chris@16: explicit operator bool()const Chris@16: { Chris@16: result_type r(*this); Chris@16: return static_cast(r); Chris@16: } Chris@16: #else Chris@16: operator unmentionable_type()const Chris@16: { Chris@16: result_type r(*this); Chris@16: return r ? &unmentionable::proc : 0; Chris@16: } Chris@16: #endif Chris@16: static const unsigned left_depth = left_type::depth + 1; Chris@16: static const unsigned left_middle_depth = left_middle_type::depth + 1; Chris@16: static const unsigned right_middle_depth = right_middle_type::depth + 1; Chris@16: static const unsigned right_depth = right_type::depth + 1; Chris@16: Chris@16: static const unsigned left_max_depth = left_depth > left_middle_depth ? left_depth : left_middle_depth; Chris@16: static const unsigned right_max_depth = right_depth > right_middle_depth ? right_depth : right_middle_depth; Chris@16: Chris@16: static const unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth; Chris@16: private: Chris@16: typename expression_storage::type arg1; Chris@16: typename expression_storage::type arg2; Chris@16: typename expression_storage::type arg3; Chris@16: typename expression_storage::type arg4; Chris@16: expression& operator=(const expression&); Chris@16: }; Chris@16: Chris@16: template Chris@16: struct digits2 Chris@16: { Chris@16: BOOST_STATIC_ASSERT(std::numeric_limits::is_specialized); Chris@16: BOOST_STATIC_ASSERT((std::numeric_limits::radix == 2) || (std::numeric_limits::radix == 10)); Chris@16: // If we really have so many digits that this fails, then we're probably going to hit other problems anyway: Chris@16: BOOST_STATIC_ASSERT(LONG_MAX / 1000 > (std::numeric_limits::digits + 1)); Chris@16: static const long value = std::numeric_limits::radix == 10 ? (((std::numeric_limits::digits + 1) * 1000L) / 301L) : std::numeric_limits::digits; Chris@16: }; Chris@16: Chris@16: #ifndef BOOST_MP_MIN_EXPONENT_DIGITS Chris@16: #ifdef _MSC_VER Chris@16: # define BOOST_MP_MIN_EXPONENT_DIGITS 2 Chris@16: #else Chris@16: # define BOOST_MP_MIN_EXPONENT_DIGITS 2 Chris@16: #endif Chris@16: #endif Chris@16: Chris@16: template Chris@16: void format_float_string(S& str, boost::intmax_t my_exp, boost::intmax_t digits, std::ios_base::fmtflags f, bool iszero) Chris@16: { Chris@16: typedef typename S::size_type size_type; Chris@16: bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific; Chris@16: bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed; Chris@16: bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint; Chris@16: bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos; Chris@16: Chris@16: bool neg = str.size() && (str[0] == '-'); Chris@16: Chris@16: if(neg) Chris@16: str.erase(0, 1); Chris@16: Chris@16: if(digits == 0) Chris@16: { Chris@16: digits = (std::max)(str.size(), size_type(16)); Chris@16: } Chris@16: Chris@16: if(iszero || str.empty() || (str.find_first_not_of('0') == S::npos)) Chris@16: { Chris@16: // We will be printing zero, even though the value might not Chris@16: // actually be zero (it just may have been rounded to zero). Chris@16: str = "0"; Chris@16: if(scientific || fixed) Chris@16: { Chris@16: str.append(1, '.'); Chris@16: str.append(size_type(digits), '0'); Chris@16: if(scientific) Chris@16: str.append("e+00"); Chris@16: } Chris@16: else Chris@16: { Chris@16: if(showpoint) Chris@16: { Chris@16: str.append(1, '.'); Chris@16: if(digits > 1) Chris@16: str.append(size_type(digits - 1), '0'); Chris@16: } Chris@16: } Chris@16: if(neg) Chris@101: str.insert(static_cast(0), 1, '-'); Chris@16: else if(showpos) Chris@101: str.insert(static_cast(0), 1, '+'); Chris@16: return; Chris@16: } Chris@16: Chris@16: if(!fixed && !scientific && !showpoint) Chris@16: { Chris@16: // Chris@16: // Suppress trailing zeros: Chris@16: // Chris@16: std::string::iterator pos = str.end(); Chris@16: while(pos != str.begin() && *--pos == '0'){} Chris@16: if(pos != str.end()) Chris@16: ++pos; Chris@16: str.erase(pos, str.end()); Chris@16: if(str.empty()) Chris@16: str = '0'; Chris@16: } Chris@16: else if(!fixed || (my_exp >= 0)) Chris@16: { Chris@16: // Chris@16: // Pad out the end with zero's if we need to: Chris@16: // Chris@16: boost::intmax_t chars = str.size(); Chris@16: chars = digits - chars; Chris@16: if(scientific) Chris@16: ++chars; Chris@16: if(chars > 0) Chris@16: { Chris@16: str.append(static_cast(chars), '0'); Chris@16: } Chris@16: } Chris@16: Chris@16: if(fixed || (!scientific && (my_exp >= -4) && (my_exp < digits))) Chris@16: { Chris@16: if(1 + my_exp > static_cast(str.size())) Chris@16: { Chris@16: // Just pad out the end with zeros: Chris@16: str.append(static_cast(1 + my_exp - str.size()), '0'); Chris@16: if(showpoint || fixed) Chris@16: str.append("."); Chris@16: } Chris@16: else if(my_exp + 1 < static_cast(str.size())) Chris@16: { Chris@16: if(my_exp < 0) Chris@16: { Chris@101: str.insert(static_cast(0), static_cast(-1 - my_exp), '0'); Chris@101: str.insert(static_cast(0), "0."); Chris@16: } Chris@16: else Chris@16: { Chris@16: // Insert the decimal point: Chris@16: str.insert(static_cast(my_exp + 1), 1, '.'); Chris@16: } Chris@16: } Chris@16: else if(showpoint || fixed) // we have exactly the digits we require to left of the point Chris@16: str += "."; Chris@16: Chris@16: if(fixed) Chris@16: { Chris@16: // We may need to add trailing zeros: Chris@16: boost::intmax_t l = str.find('.') + 1; Chris@16: l = digits - (str.size() - l); Chris@16: if(l > 0) Chris@16: str.append(size_type(l), '0'); Chris@16: } Chris@16: } Chris@16: else Chris@16: { Chris@16: BOOST_MP_USING_ABS Chris@16: // Scientific format: Chris@16: if(showpoint || (str.size() > 1)) Chris@101: str.insert(static_cast(1u), 1, '.'); Chris@101: str.append(static_cast(1u), 'e'); Chris@16: S e = boost::lexical_cast(abs(my_exp)); Chris@16: if(e.size() < BOOST_MP_MIN_EXPONENT_DIGITS) Chris@101: e.insert(static_cast(0), BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0'); Chris@16: if(my_exp < 0) Chris@101: e.insert(static_cast(0), 1, '-'); Chris@16: else Chris@101: e.insert(static_cast(0), 1, '+'); Chris@16: str.append(e); Chris@16: } Chris@16: if(neg) Chris@101: str.insert(static_cast(0), 1, '-'); Chris@16: else if(showpos) Chris@101: str.insert(static_cast(0), 1, '+'); Chris@16: } Chris@16: Chris@16: template Chris@16: void check_shift_range(V val, const mpl::true_&, const mpl::true_&) Chris@16: { Chris@16: if(val > (std::numeric_limits::max)()) Chris@16: BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits::max().")); Chris@16: if(val < 0) Chris@16: BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value.")); Chris@16: } Chris@16: template Chris@16: void check_shift_range(V val, const mpl::false_&, const mpl::true_&) Chris@16: { Chris@16: if(val < 0) Chris@16: BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value.")); Chris@16: } Chris@16: template Chris@16: void check_shift_range(V val, const mpl::true_&, const mpl::false_&) Chris@16: { Chris@16: if(val > (std::numeric_limits::max)()) Chris@16: BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits::max().")); Chris@16: } Chris@16: template Chris@16: void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT{} Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: // Chris@16: // Traits class, lets us know what kind of number we have, defaults to a floating point type: Chris@16: // Chris@16: enum number_category_type Chris@16: { Chris@16: number_kind_unknown = -1, Chris@16: number_kind_integer = 0, Chris@16: number_kind_floating_point = 1, Chris@16: number_kind_rational = 2, Chris@16: number_kind_fixed_point = 3 Chris@16: }; Chris@16: Chris@16: template Chris@16: struct number_category : public mpl::int_::is_integer ? number_kind_integer : (std::numeric_limits::max_exponent ? number_kind_floating_point : number_kind_unknown)> {}; Chris@16: template Chris@16: struct number_category > : public number_category{}; Chris@16: template Chris@16: struct number_category > : public number_category::result_type>{}; Chris@16: Chris@16: template Chris@16: struct component_type; Chris@16: template Chris@16: struct component_type > : public component_type{}; Chris@16: template Chris@16: struct component_type > : public component_type::result_type>{}; Chris@16: Chris@16: template Chris@16: struct is_unsigned_number : public mpl::false_{}; Chris@16: template Chris@16: struct is_unsigned_number > : public is_unsigned_number {}; Chris@16: template Chris@16: struct is_signed_number : public mpl::bool_::value> {}; Chris@16: template Chris@16: struct is_interval_number : public mpl::false_ {}; Chris@16: template Chris@16: struct is_interval_number > : public is_interval_number{}; Chris@16: Chris@16: }} // namespaces Chris@16: Chris@16: namespace boost{ namespace math{ namespace tools{ Chris@16: Chris@16: template Chris@16: struct promote_arg; Chris@16: Chris@16: template Chris@16: struct promote_arg > Chris@16: { Chris@16: typedef typename boost::multiprecision::detail::expression::result_type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline R real_cast(const boost::multiprecision::number& val) Chris@16: { Chris@16: return val.template convert_to(); Chris@16: } Chris@16: Chris@16: template Chris@16: inline R real_cast(const boost::multiprecision::detail::expression& val) Chris@16: { Chris@16: typedef typename boost::multiprecision::detail::expression::result_type val_type; Chris@16: return val_type(val).template convert_to(); Chris@16: } Chris@16: Chris@16: Chris@101: } Chris@101: Chris@101: namespace constants{ Chris@101: Chris@101: template Chris@101: struct is_explicitly_convertible_from_string; Chris@101: Chris@101: template Chris@101: struct is_explicitly_convertible_from_string > Chris@101: { Chris@101: static const bool value = true; Chris@101: }; Chris@101: Chris@101: } Chris@101: Chris@101: }} Chris@16: Chris@16: #endif // BOOST_MATH_BIG_NUM_BASE_HPP Chris@16: Chris@16: