mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-02-19 14:32:35 +00:00
Add scalbn and logb functions, plus float->rational generic conversion (base 2 only at present).
This commit is contained in:
@@ -2805,6 +2805,21 @@ inline void eval_trunc(cpp_dec_float<Digits10, ExponentType, Allocator>& result,
|
||||
result = x.extract_integer_part();
|
||||
}
|
||||
|
||||
template <unsigned Digits10, class ExponentType, class Allocator>
|
||||
inline void eval_logb(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val)
|
||||
{
|
||||
// Set result, to the exponent of val:
|
||||
result = static_cast<long long>(val.order());
|
||||
}
|
||||
template <unsigned Digits10, class ExponentType, class Allocator, class ArgType>
|
||||
inline void eval_scalbn(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val, ArgType e_)
|
||||
{
|
||||
using default_ops::eval_multiply;
|
||||
const ExponentType e = e_;
|
||||
cpp_dec_float<Digits10, ExponentType, Allocator> t(1.0, e);
|
||||
eval_multiply(result, val, t);
|
||||
}
|
||||
|
||||
template <unsigned Digits10, class ExponentType, class Allocator, class ArgType>
|
||||
inline void eval_ldexp(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x, ArgType e)
|
||||
{
|
||||
|
||||
@@ -1202,6 +1202,23 @@ template <class T>
|
||||
typename enable_if_c<sizeof(T) == 0>::type eval_ldexp();
|
||||
template <class T>
|
||||
typename enable_if_c<sizeof(T) == 0>::type eval_frexp();
|
||||
|
||||
//
|
||||
// eval_logb and eval_scalbn simply assume base 2 and forward to
|
||||
// eval_ldexp and eval_frexp:
|
||||
//
|
||||
template <class B>
|
||||
inline void eval_logb(B& result, const B& val)
|
||||
{
|
||||
typename B::exponent_type e;
|
||||
eval_frexp(result, val, &e);
|
||||
result = static_cast<boost::intmax_t>(e);
|
||||
}
|
||||
template <class B, class A>
|
||||
inline void eval_scalbn(B& result, const B& val, A e)
|
||||
{
|
||||
eval_ldexp(result, val, static_cast<typename B::exponent_type>(e));
|
||||
}
|
||||
//
|
||||
// These functions are implemented in separate files, but expanded inline here,
|
||||
// DO NOT CHANGE THE ORDER OF THESE INCLUDES:
|
||||
@@ -2019,6 +2036,12 @@ BINARY_OP_FUNCTOR(pow, number_kind_floating_point)
|
||||
BINARY_OP_FUNCTOR(fmod, number_kind_floating_point)
|
||||
BINARY_OP_FUNCTOR(atan2, number_kind_floating_point)
|
||||
|
||||
UNARY_OP_FUNCTOR(logb, number_kind_floating_point)
|
||||
HETERO_BINARY_OP_FUNCTOR(scalbn, short, number_kind_floating_point)
|
||||
HETERO_BINARY_OP_FUNCTOR_B(scalbn, int, number_kind_floating_point)
|
||||
HETERO_BINARY_OP_FUNCTOR_B(scalbn, long, number_kind_floating_point)
|
||||
HETERO_BINARY_OP_FUNCTOR_B(scalbn, long long, number_kind_floating_point)
|
||||
|
||||
//
|
||||
// Integer functions:
|
||||
//
|
||||
|
||||
@@ -222,6 +222,43 @@ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_
|
||||
eval_divide(to, fn.backend(), fd.backend());
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class To, class From>
|
||||
void generic_interconvert_float2rational(To& to, const From& from, const mpl::int_<2>& /*radix*/)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
typedef typename mpl::front<typename To::unsigned_types>::type ui_type;
|
||||
static const int shift = std::numeric_limits<long long>::digits;
|
||||
typename From::exponent_type e;
|
||||
typename component_type<To>::type num, denom;
|
||||
number<From> val(from);
|
||||
val = frexp(val, &e);
|
||||
while(val)
|
||||
{
|
||||
val = ldexp(val, shift);
|
||||
e -= shift;
|
||||
long long ll = boost::math::lltrunc(val);
|
||||
val -= ll;
|
||||
num <<= shift;
|
||||
num += ll;
|
||||
}
|
||||
denom = ui_type(1u);
|
||||
if(e < 0)
|
||||
denom <<= -e;
|
||||
else if(e > 0)
|
||||
num <<= e;
|
||||
assign_components(to, num, denom);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/)
|
||||
{
|
||||
detail::generic_interconvert_float2rational(to, from, mpl::int_<std::numeric_limits<number<From> >::radix>());
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MP_GENERIC_INTERCONVERT_HPP
|
||||
|
||||
Reference in New Issue
Block a user