Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions extra/decimal_printer_lldb.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,26 @@ def decimal_fast128_summary(valobj, internal_dict):
except Exception as e:
return f"<invalid decimal_fast128_t: {e}>"

def u256_summary(valobj, internal_dict):
"""
Custom summary for u256 detail type
Displays in decimal notation
"""

try:
val = valobj.GetNonSyntheticValue()

bytes = val.GetChildMemberWithName("bytes")
b0 = bytes.GetChildAtIndex(0).GetValueAsUnsigned()
b1 = bytes.GetChildAtIndex(1).GetValueAsUnsigned()
b2 = bytes.GetChildAtIndex(2).GetValueAsUnsigned()
b3 = bytes.GetChildAtIndex(3).GetValueAsUnsigned()

value = (b3 << 192) | (b2 << 128) | (b1 << 64) | b0
return f"{value:,}"
except Exception as e:
return f"<invalid u256: {e}>"

def __lldb_init_module(debugger, internal_dict):
decimal32_pattern = r"^(const )?(boost::decimal::decimal32_t|(\w+::)*decimal32_t)( &| \*)?$"
decimal64_pattern = r"^(const )?(boost::decimal::decimal64_t|(\w+::)*decimal64_t)( &| \*)?$"
Expand All @@ -118,6 +138,8 @@ def __lldb_init_module(debugger, internal_dict):
decimal_fast64_pattern = r"^(const )?(boost::decimal::decimal_fast64_t|(\w+::)*decimal_fast64_t)( &| \*)?$"
decimal_fast128_pattern = r"^(const )?(boost::decimal::decimal_fast128_t|(\w+::)*decimal_fast128_t)( &| \*)?$"

u256_pattern = r"^(const )?(boost::decimal::detail::u256|(\w+::)*u256)( &| \*)?$"

debugger.HandleCommand(
f'type summary add -x "{decimal32_pattern}" -e -F decimal_printer_lldb.decimal32_summary'
)
Expand Down Expand Up @@ -172,6 +194,13 @@ def __lldb_init_module(debugger, internal_dict):

print("decimal_fast128_t printer loaded successfully")

debugger.HandleCommand(
f'type summary add -x "{u256_pattern}" -e -F decimal_printer_lldb.u256_summary'
)
debugger.HandleCommand(
f'type synthetic add -x "{u256_pattern}" -l decimal_printer_lldb.u256SyntheticProvider'
)

class DecimalSyntheticProvider:
def __init__(self, valobj, internal_dict):
self.valobj = valobj
Expand Down Expand Up @@ -228,3 +257,25 @@ def update(self):
def has_children(self):
return True

class u256SyntheticProvider:
def __init__(self, valobj, internal_dict):
self.valobj = valobj

def num_children(self):
return 1

def get_child_index(self, name):
if name == "bytes":
return 0
return -1

def get_child_at_index(self, index):
if index == 0:
return self.valobj.GetChildMemberWithName("bytes")
return None

def update(self):
pass

def has_children(self):
return True
13 changes: 3 additions & 10 deletions include/boost/decimal/decimal128_t.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1708,17 +1708,10 @@ constexpr auto operator+(const decimal128_t& lhs, const decimal128_t& rhs) noexc
}
#endif

auto lhs_sig {lhs.full_significand()};
auto lhs_exp {lhs.biased_exponent()};
detail::expand_significand<decimal128_t>(lhs_sig, lhs_exp);

auto rhs_sig {rhs.full_significand()};
auto rhs_exp {rhs.biased_exponent()};
detail::expand_significand<decimal128_t>(rhs_sig, rhs_exp);
const auto lhs_components {lhs.to_components()};
const auto rhs_components {rhs.to_components()};

return detail::d128_add_impl<decimal128_t>(lhs_sig, lhs_exp, lhs.isneg(),
rhs_sig, rhs_exp, rhs.isneg(),
abs(lhs) > abs(rhs));
return detail::d128_add_impl_new<decimal128_t>(lhs_components, rhs_components);
}

template <typename Integer>
Expand Down
186 changes: 186 additions & 0 deletions include/boost/decimal/detail/add_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <boost/decimal/detail/power_tables.hpp>
#include <boost/decimal/detail/promotion.hpp>
#include <boost/decimal/detail/is_power_of_10.hpp>
#include <boost/decimal/detail/i256.hpp>
#include "int128.hpp"

#ifndef BOOST_DECIMAL_BUILD_MODULE
Expand Down Expand Up @@ -188,6 +189,191 @@ constexpr auto add_impl(const T& lhs, const T& rhs) noexcept -> ReturnType
return ReturnType{return_sig, lhs_exp, new_sig < 0};
}

template <typename ReturnType, typename T>
constexpr auto d128_add_impl_new(const T& lhs, const T& rhs) noexcept -> ReturnType
{
using promoted_sig_type = u256;

auto big_lhs {lhs.full_significand()};
auto big_rhs {rhs.full_significand()};
auto lhs_exp {lhs.biased_exponent()};
auto rhs_exp {rhs.biased_exponent()};
promoted_sig_type promoted_lhs {big_lhs};
promoted_sig_type promoted_rhs {big_rhs};

// Align to larger exponent
if (lhs_exp != rhs_exp)
{
constexpr auto max_shift {detail::make_positive_unsigned(std::numeric_limits<promoted_sig_type>::digits10 - detail::precision_v<ReturnType> - 1)};
const auto shift {detail::make_positive_unsigned(lhs_exp - rhs_exp)};

if (shift > max_shift)
{
auto round {_boost_decimal_global_rounding_mode};

#ifndef BOOST_DECIMAL_NO_CONSTEVAL_DETECTION

if (!BOOST_DECIMAL_IS_CONSTANT_EVALUATED(lhs))
{
round = fegetround();
}

#endif

if (BOOST_DECIMAL_LIKELY(round != rounding_mode::fe_dec_downward && round != rounding_mode::fe_dec_upward))
{
return big_lhs != 0U && (lhs_exp > rhs_exp) ?
ReturnType{lhs.full_significand(), lhs.biased_exponent(), lhs.isneg()} :
ReturnType{rhs.full_significand(), rhs.biased_exponent(), rhs.isneg()};
}
else if (round == rounding_mode::fe_dec_downward)
{
// If we are subtracting even disparate numbers we need to round down
// E.g. "5e+95"_DF - "4e-100"_DF == "4.999999e+95"_DF
const auto use_lhs {big_lhs != 0U && (lhs_exp > rhs_exp)};

// Need to check for the case where we have 1e+95 - anything = 9.99999... without losing a nine
if (use_lhs)
{
if (big_rhs != 0U && (lhs.isneg() != rhs.isneg()))
{
if (is_power_of_10(big_lhs))
{
--big_lhs;
big_lhs *= 10U;
big_lhs += 9U;
--lhs_exp;
}
else
{
--big_lhs;
}
}

return ReturnType{big_lhs, lhs_exp, lhs.isneg()};
}
else
{
if (big_lhs != 0U && (lhs.isneg() != rhs.isneg()))
{
if (is_power_of_10(big_rhs))
{
--big_rhs;
big_rhs *= 10U;
big_rhs += 9U;
--rhs_exp;
}
else
{
--big_rhs;
}
}

return ReturnType{big_rhs, rhs_exp, rhs.isneg()};
}
}
else
{
// rounding mode == fe_dec_upward
// Unconditionally round up. Could be 5e+95 + 4e-100 -> 5.000001e+95
const bool use_lhs {big_lhs != 0U && (lhs_exp > rhs_exp)};

if (use_lhs)
{
if (big_rhs != 0U)
{
if (lhs.isneg() != rhs.isneg())
{
if (is_power_of_10(big_lhs))
{
--big_lhs;
big_lhs *= 10U;
big_lhs += 9U;
--lhs_exp;
}
else
{
--big_lhs;
}
}
else
{
++big_lhs;
}
}

return ReturnType{big_lhs, lhs_exp, lhs.isneg()} ;
}
else
{
if (big_lhs != 0U)
{
if (rhs.isneg() != lhs.isneg())
{
--big_rhs;
big_rhs *= 10U;
big_rhs += 9U;
--rhs_exp;
}
else
{
++big_rhs;
}
}

return ReturnType{big_rhs, rhs_exp, rhs.isneg()};
}
}
}

if (lhs_exp < rhs_exp)
{
promoted_rhs *= detail::pow10<promoted_sig_type>(shift);
lhs_exp = rhs_exp - static_cast<decltype(lhs_exp)>(shift);
}
else
{
const auto shift_pow10 {detail::pow10(static_cast<promoted_sig_type>(shift))};
promoted_lhs *= shift_pow10;
lhs_exp -= static_cast<decltype(lhs_exp)>(shift);
}
}

u256 return_sig {};
bool return_sign {};
const auto lhs_sign {lhs.isneg()};
const auto rhs_sign {rhs.isneg()};

if (lhs_sign && !rhs_sign)
{
// -lhs + rhs = rhs - lhs
return_sign = i256_sub(promoted_rhs, promoted_lhs, return_sig);
}
else if (!lhs_sign && rhs_sign)
{
// lhs - rhs
return_sign = i256_sub(promoted_lhs, promoted_rhs, return_sig);
}
else
{
// lhs + rhs or -lhs + -rhs
return_sig = promoted_lhs + promoted_rhs;
return_sign = lhs_sign && rhs_sign;
}

BOOST_DECIMAL_IF_CONSTEXPR (detail::decimal_val_v<ReturnType> == 128)
{
// In the regular 128-bit case there's a chance the high words are empty,
// and we can just convert to 128-bit arithmetic now
if (return_sig[2] == 0U && return_sig[3] == 0U)
{
return ReturnType{static_cast<int128::uint128_t>(return_sig), lhs_exp, return_sign};
}
}

return ReturnType{return_sig, lhs_exp, return_sign};
}

template <typename ReturnType, typename T, typename U>
constexpr auto d128_add_impl(T lhs_sig, U lhs_exp, bool lhs_sign,
T rhs_sig, U rhs_exp, bool rhs_sign,
Expand Down
4 changes: 4 additions & 0 deletions include/boost/decimal/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,10 @@
# endif
# if defined(__ADX__) && defined(BOOST_DECIMAL_HAS_MSVC_64BIT_INTRINSICS)
# define BOOST_DECIMAL_ADD_CARRY _addcarryx_u64
# define BOOST_DECIMAL_SUB_BORROW _subborrow_u64
# elif defined(BOOST_DECIMAL_HAS_MSVC_64BIT_INTRINSICS)
# define BOOST_DECIMAL_ADD_CARRY _addcarry_u64
# define BOOST_DECIMAL_SUB_BORROW _subborrow_u64
# endif
#elif defined(__x86_64__)
# ifndef BOOST_DECIMAL_BUILD_MODULE
Expand All @@ -107,8 +109,10 @@
# define BOOST_DECIMAL_HAS_X64_INTRINSICS
# ifdef __ADX__
# define BOOST_DECIMAL_ADD_CARRY _addcarryx_u64
# define BOOST_DECIMAL_SUB_BORROW _subborrow_u64
# else
# define BOOST_DECIMAL_ADD_CARRY _addcarry_u64
# define BOOST_DECIMAL_SUB_BORROW _subborrow_u64
# endif
#elif defined(__ARM_NEON__)
# ifndef BOOST_DECIMAL_BUILD_MODULE
Expand Down
Loading
Loading