Skip to content

Commit 1def358

Browse files
authored
Merge pull request #1288 from cppalliance/i256
2 parents 88a0966 + 653aa3c commit 1def358

File tree

13 files changed

+787
-171
lines changed

13 files changed

+787
-171
lines changed

extra/decimal_printer_gdb.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,27 @@ def children(self):
138138
yield ('sign_', self.val['sign_'])
139139

140140

141+
class U256Printer:
142+
"""Pretty printer for u256 internal type"""
143+
144+
def __init__(self, val):
145+
self.val = val
146+
147+
def to_string(self):
148+
try:
149+
bytes = self.val['bytes']
150+
byte0 = int(bytes[3]) & 0xFFFFFFFFFFFFFFFF
151+
byte1 = int(bytes[2]) & 0xFFFFFFFFFFFFFFFF
152+
byte2 = int(bytes[1]) & 0xFFFFFFFFFFFFFFFF
153+
byte3 = int(bytes[0]) & 0xFFFFFFFFFFFFFFFF
154+
155+
value = (byte0 << 192) | (byte1 << 128) | (byte2 << 64) | byte3
156+
return f"{value:,}"
157+
except Exception as e:
158+
return f"<invalid u256: {e}>"
159+
160+
161+
141162
def build_pretty_printer():
142163
"""Build and return the pretty printer collection"""
143164
pp = gdb.printing.RegexpCollectionPrettyPrinter("boost_decimal")
@@ -164,6 +185,11 @@ def build_pretty_printer():
164185
r'^(const )?(boost::decimal::)?decimal_fast128_t( &| \*)?$',
165186
DecimalFast128Printer)
166187

188+
# Debug internal types
189+
pp.add_printer('u256',
190+
r'^(const )?(boost::decimal::detail::)?u256( &| \*)?$',
191+
U256Printer)
192+
167193
return pp
168194

169195

extra/decimal_printer_lldb.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,26 @@ def decimal_fast128_summary(valobj, internal_dict):
109109
except Exception as e:
110110
return f"<invalid decimal_fast128_t: {e}>"
111111

112+
def u256_summary(valobj, internal_dict):
113+
"""
114+
Custom summary for u256 detail type
115+
Displays in decimal notation
116+
"""
117+
118+
try:
119+
val = valobj.GetNonSyntheticValue()
120+
121+
bytes = val.GetChildMemberWithName("bytes")
122+
b0 = bytes.GetChildAtIndex(0).GetValueAsUnsigned()
123+
b1 = bytes.GetChildAtIndex(1).GetValueAsUnsigned()
124+
b2 = bytes.GetChildAtIndex(2).GetValueAsUnsigned()
125+
b3 = bytes.GetChildAtIndex(3).GetValueAsUnsigned()
126+
127+
value = (b3 << 192) | (b2 << 128) | (b1 << 64) | b0
128+
return f"{value:,}"
129+
except Exception as e:
130+
return f"<invalid u256: {e}>"
131+
112132
def __lldb_init_module(debugger, internal_dict):
113133
decimal32_pattern = r"^(const )?(boost::decimal::decimal32_t|(\w+::)*decimal32_t)( &| \*)?$"
114134
decimal64_pattern = r"^(const )?(boost::decimal::decimal64_t|(\w+::)*decimal64_t)( &| \*)?$"
@@ -118,6 +138,8 @@ def __lldb_init_module(debugger, internal_dict):
118138
decimal_fast64_pattern = r"^(const )?(boost::decimal::decimal_fast64_t|(\w+::)*decimal_fast64_t)( &| \*)?$"
119139
decimal_fast128_pattern = r"^(const )?(boost::decimal::decimal_fast128_t|(\w+::)*decimal_fast128_t)( &| \*)?$"
120140

141+
u256_pattern = r"^(const )?(boost::decimal::detail::u256|(\w+::)*u256)( &| \*)?$"
142+
121143
debugger.HandleCommand(
122144
f'type summary add -x "{decimal32_pattern}" -e -F decimal_printer_lldb.decimal32_summary'
123145
)
@@ -172,6 +194,13 @@ def __lldb_init_module(debugger, internal_dict):
172194

173195
print("decimal_fast128_t printer loaded successfully")
174196

197+
debugger.HandleCommand(
198+
f'type summary add -x "{u256_pattern}" -e -F decimal_printer_lldb.u256_summary'
199+
)
200+
debugger.HandleCommand(
201+
f'type synthetic add -x "{u256_pattern}" -l decimal_printer_lldb.u256SyntheticProvider'
202+
)
203+
175204
class DecimalSyntheticProvider:
176205
def __init__(self, valobj, internal_dict):
177206
self.valobj = valobj
@@ -228,3 +257,25 @@ def update(self):
228257
def has_children(self):
229258
return True
230259

260+
class u256SyntheticProvider:
261+
def __init__(self, valobj, internal_dict):
262+
self.valobj = valobj
263+
264+
def num_children(self):
265+
return 1
266+
267+
def get_child_index(self, name):
268+
if name == "bytes":
269+
return 0
270+
return -1
271+
272+
def get_child_at_index(self, index):
273+
if index == 0:
274+
return self.valobj.GetChildMemberWithName("bytes")
275+
return None
276+
277+
def update(self):
278+
pass
279+
280+
def has_children(self):
281+
return True

include/boost/decimal/decimal128_t.hpp

Lines changed: 25 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,24 +1708,20 @@ constexpr auto operator+(const decimal128_t& lhs, const decimal128_t& rhs) noexc
17081708
}
17091709
#endif
17101710

1711-
auto lhs_sig {lhs.full_significand()};
1712-
auto lhs_exp {lhs.biased_exponent()};
1713-
detail::expand_significand<decimal128_t>(lhs_sig, lhs_exp);
1714-
1715-
auto rhs_sig {rhs.full_significand()};
1716-
auto rhs_exp {rhs.biased_exponent()};
1717-
detail::expand_significand<decimal128_t>(rhs_sig, rhs_exp);
1711+
auto lhs_components {lhs.to_components()};
1712+
detail::expand_significand<decimal128_t>(lhs_components.sig, lhs_components.exp);
1713+
auto rhs_components {rhs.to_components()};
1714+
detail::expand_significand<decimal128_t>(rhs_components.sig, rhs_components.exp);
17181715

1719-
return detail::d128_add_impl<decimal128_t>(lhs_sig, lhs_exp, lhs.isneg(),
1720-
rhs_sig, rhs_exp, rhs.isneg(),
1721-
abs(lhs) > abs(rhs));
1716+
return detail::d128_add_impl_new<decimal128_t>(lhs_components, rhs_components);
17221717
}
17231718

17241719
template <typename Integer>
17251720
constexpr auto operator+(const decimal128_t lhs, const Integer rhs) noexcept
17261721
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_t)
17271722
{
17281723
using exp_type = decimal128_t::biased_exponent_type;
1724+
using sig_type = decimal128_t::significand_type;
17291725

17301726
#ifndef BOOST_DECIMAL_FAST_MATH
17311727
if (not_finite(lhs))
@@ -1734,19 +1730,15 @@ constexpr auto operator+(const decimal128_t lhs, const Integer rhs) noexcept
17341730
}
17351731
#endif
17361732

1737-
auto sig_rhs {static_cast<int128::uint128_t>(detail::make_positive_unsigned(rhs))};
1738-
bool abs_lhs_bigger {abs(lhs) > sig_rhs};
1739-
1740-
auto sig_lhs {lhs.full_significand()};
1741-
auto exp_lhs {lhs.biased_exponent()};
1742-
detail::expand_significand<decimal128_t>(sig_lhs, exp_lhs);
1733+
auto lhs_components {lhs.to_components()};
1734+
detail::expand_significand<decimal128_t>(lhs_components.sig, lhs_components.exp);
17431735

1736+
auto positive_rhs {static_cast<sig_type>(detail::make_positive_unsigned(rhs))};
17441737
exp_type exp_rhs {0};
1745-
detail::normalize<decimal128_t>(sig_rhs, exp_rhs);
1738+
detail::normalize<decimal128_t>(positive_rhs, exp_rhs);
1739+
const detail::decimal128_t_components rhs_components {positive_rhs, exp_rhs, rhs < 0};
17461740

1747-
return detail::d128_add_impl<decimal128_t>(sig_lhs, exp_lhs, lhs.isneg(),
1748-
sig_rhs, exp_rhs, (rhs < 0),
1749-
abs_lhs_bigger);
1741+
return detail::d128_add_impl_new<decimal128_t>(lhs_components, rhs_components);
17501742
}
17511743

17521744
template <typename Integer>
@@ -1771,25 +1763,21 @@ constexpr auto operator-(const decimal128_t& lhs, const decimal128_t& rhs) noexc
17711763
}
17721764
#endif
17731765

1774-
auto sig_lhs {lhs.full_significand()};
1775-
auto exp_lhs {lhs.biased_exponent()};
1776-
detail::expand_significand<decimal128_t>(sig_lhs, exp_lhs);
1777-
1778-
auto sig_rhs {rhs.full_significand()};
1779-
auto exp_rhs {rhs.biased_exponent()};
1780-
detail::expand_significand<decimal128_t>(sig_rhs, exp_rhs);
1766+
auto lhs_components {lhs.to_components()};
1767+
detail::expand_significand<decimal128_t>(lhs_components.sig, lhs_components.exp);
1768+
auto rhs_components {rhs.to_components()};
1769+
detail::expand_significand<decimal128_t>(rhs_components.sig, rhs_components.exp);
1770+
rhs_components.sign = !rhs_components.sign;
17811771

1782-
return detail::d128_add_impl<decimal128_t>(
1783-
sig_lhs, exp_lhs, lhs.isneg(),
1784-
sig_rhs, exp_rhs, !rhs.isneg(),
1785-
abs(lhs) > abs(rhs));
1772+
return detail::d128_add_impl_new<decimal128_t>(lhs_components, rhs_components);
17861773
}
17871774

17881775
template <typename Integer>
17891776
constexpr auto operator-(const decimal128_t lhs, const Integer rhs) noexcept
17901777
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_t)
17911778
{
17921779
using exp_type = decimal128_t::biased_exponent_type;
1780+
using sig_type = decimal128_t::significand_type;
17931781

17941782
#ifndef BOOST_DECIMAL_FAST_MATH
17951783
if (not_finite(lhs))
@@ -1798,49 +1786,29 @@ constexpr auto operator-(const decimal128_t lhs, const Integer rhs) noexcept
17981786
}
17991787
#endif
18001788

1801-
auto sig_rhs {static_cast<int128::uint128_t>(detail::make_positive_unsigned(rhs))};
1802-
const bool abs_lhs_bigger {abs(lhs) > sig_rhs};
1803-
1804-
auto sig_lhs {lhs.full_significand()};
1805-
auto exp_lhs {lhs.biased_exponent()};
1806-
detail::expand_significand<decimal128_t>(sig_lhs, exp_lhs);
1789+
auto lhs_components {lhs.to_components()};
1790+
detail::expand_significand<decimal128_t>(lhs_components.sig, lhs_components.exp);
18071791

1792+
auto sig_rhs {static_cast<sig_type>(detail::make_positive_unsigned(rhs))};
18081793
exp_type exp_rhs {0};
18091794
detail::normalize<decimal128_t>(sig_rhs, exp_rhs);
1795+
const detail::decimal128_t_components rhs_components {sig_rhs, exp_rhs, !(rhs < 0)};
18101796

1811-
return detail::d128_add_impl<decimal128_t>(
1812-
sig_lhs, exp_lhs, lhs.isneg(),
1813-
sig_rhs, exp_rhs, !(rhs < 0),
1814-
abs_lhs_bigger);
1797+
return detail::d128_add_impl_new<decimal128_t>(lhs_components, rhs_components);
18151798
}
18161799

18171800
template <typename Integer>
18181801
constexpr auto operator-(const Integer lhs, const decimal128_t rhs) noexcept
18191802
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_t)
18201803
{
1821-
using exp_type = decimal128_t::biased_exponent_type;
1822-
18231804
#ifndef BOOST_DECIMAL_FAST_MATH
18241805
if (not_finite(rhs))
18251806
{
18261807
return detail::check_non_finite(rhs);
18271808
}
18281809
#endif
18291810

1830-
auto sig_lhs {static_cast<int128::uint128_t>(detail::make_positive_unsigned(lhs))};
1831-
const bool abs_lhs_bigger {sig_lhs > abs(rhs)};
1832-
1833-
exp_type exp_lhs {0};
1834-
detail::normalize<decimal128_t>(sig_lhs, exp_lhs);
1835-
1836-
auto sig_rhs {rhs.full_significand()};
1837-
auto exp_rhs {rhs.biased_exponent()};
1838-
detail::expand_significand<decimal128_t>(sig_rhs, exp_rhs);
1839-
1840-
return detail::d128_add_impl<decimal128_t>(
1841-
sig_lhs, exp_lhs, (lhs < 0),
1842-
sig_rhs, exp_rhs, !rhs.isneg(),
1843-
abs_lhs_bigger);
1811+
return -rhs + lhs;
18441812
}
18451813

18461814
constexpr auto operator*(const decimal128_t& lhs, const decimal128_t& rhs) noexcept -> decimal128_t

include/boost/decimal/decimal_fast128_t.hpp

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@ BOOST_DECIMAL_EXPORT class alignas(16) decimal_fast128_t final
225225
template <typename Decimal>
226226
friend constexpr Decimal detail::check_non_finite(Decimal x) noexcept;
227227

228+
template <typename ReturnType, typename T>
229+
friend constexpr auto detail::d128_add_impl_new(const T& lhs, const T& rhs) noexcept -> ReturnType;
230+
228231
public:
229232
constexpr decimal_fast128_t() noexcept = default;
230233

@@ -1032,17 +1035,15 @@ constexpr auto operator+(const decimal_fast128_t& lhs, const decimal_fast128_t&
10321035
}
10331036
#endif
10341037

1035-
return detail::d128_add_impl<decimal_fast128_t>(
1036-
lhs.significand_, lhs.biased_exponent(), lhs.sign_,
1037-
rhs.significand_, rhs.biased_exponent(), rhs.sign_,
1038-
(abs(lhs) > abs(rhs)));
1038+
return detail::d128_add_impl_new<decimal_fast128_t>(lhs, rhs);
10391039
}
10401040

10411041
template <typename Integer>
10421042
constexpr auto operator+(const decimal_fast128_t& lhs, const Integer rhs) noexcept
10431043
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal_fast128_t)
10441044
{
10451045
using exp_type = decimal_fast128_t::biased_exponent_type;
1046+
using sig_type = decimal_fast128_t::significand_type;
10461047

10471048
#ifndef BOOST_DECIMAL_FAST_MATH
10481049
if (not_finite(lhs))
@@ -1051,15 +1052,12 @@ constexpr auto operator+(const decimal_fast128_t& lhs, const Integer rhs) noexce
10511052
}
10521053
#endif
10531054

1054-
auto sig_rhs {static_cast<int128::uint128_t>(detail::make_positive_unsigned(rhs))};
1055-
bool abs_lhs_bigger {abs(lhs) > sig_rhs};
1056-
1055+
auto sig_rhs {static_cast<sig_type>(detail::make_positive_unsigned(rhs))};
10571056
exp_type exp_rhs {0};
10581057
detail::normalize<decimal_fast128_t>(sig_rhs, exp_rhs);
1058+
const detail::decimal_fast128_t_components rhs_components {sig_rhs, exp_rhs, rhs < 0};
10591059

1060-
return detail::d128_add_impl<decimal_fast128_t>(lhs.significand_, lhs.biased_exponent(), lhs.sign_,
1061-
sig_rhs, exp_rhs, (rhs < 0),
1062-
abs_lhs_bigger);
1060+
return detail::d128_add_impl_new<decimal_fast128_t>(lhs.to_components(), rhs_components);
10631061
}
10641062

10651063
template <typename Integer>
@@ -1083,17 +1081,15 @@ constexpr auto operator-(const decimal_fast128_t& lhs, const decimal_fast128_t&
10831081
}
10841082
#endif
10851083

1086-
return detail::d128_add_impl<decimal_fast128_t>(
1087-
lhs.significand_, lhs.biased_exponent(), lhs.sign_,
1088-
rhs.significand_, rhs.biased_exponent(), !rhs.sign_,
1089-
abs(lhs) > abs(rhs));
1084+
return detail::d128_add_impl_new<decimal_fast128_t>(lhs, -rhs);
10901085
}
10911086

10921087
template <typename Integer>
10931088
constexpr auto operator-(const decimal_fast128_t& lhs, const Integer rhs) noexcept
10941089
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal_fast128_t)
10951090
{
10961091
using exp_type = decimal_fast128_t::biased_exponent_type;
1092+
using sig_type = decimal_fast128_t::significand_type;
10971093

10981094
#ifndef BOOST_DECIMAL_FAST_MATH
10991095
if (not_finite(lhs))
@@ -1102,41 +1098,26 @@ constexpr auto operator-(const decimal_fast128_t& lhs, const Integer rhs) noexce
11021098
}
11031099
#endif
11041100

1105-
auto sig_rhs {static_cast<int128::uint128_t>(detail::make_positive_unsigned(rhs))};
1106-
const bool abs_lhs_bigger {abs(lhs) > sig_rhs};
1107-
1101+
auto sig_rhs {static_cast<sig_type>(detail::make_positive_unsigned(rhs))};
11081102
exp_type exp_rhs {0};
11091103
detail::normalize<decimal_fast128_t>(sig_rhs, exp_rhs);
1104+
const detail::decimal_fast128_t_components rhs_components {sig_rhs, exp_rhs, !(rhs < 0)};
11101105

1111-
return detail::d128_add_impl<decimal_fast128_t>(
1112-
lhs.significand_, lhs.biased_exponent(), lhs.sign_,
1113-
sig_rhs, exp_rhs, !(rhs < 0),
1114-
abs_lhs_bigger);
1106+
return detail::d128_add_impl_new<decimal_fast128_t>(lhs.to_components(), rhs_components);
11151107
}
11161108

11171109
template <typename Integer>
11181110
constexpr auto operator-(const Integer lhs, const decimal_fast128_t& rhs) noexcept
11191111
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal_fast128_t)
11201112
{
1121-
using exp_type = decimal_fast128_t::biased_exponent_type;
1122-
11231113
#ifndef BOOST_DECIMAL_FAST_MATH
11241114
if (not_finite(rhs))
11251115
{
11261116
return detail::check_non_finite(rhs);
11271117
}
11281118
#endif
11291119

1130-
auto sig_lhs {static_cast<int128::uint128_t>(detail::make_positive_unsigned(lhs))};
1131-
const bool abs_lhs_bigger {sig_lhs > abs(rhs)};
1132-
1133-
exp_type exp_lhs {0};
1134-
detail::normalize<decimal_fast128_t>(sig_lhs, exp_lhs);
1135-
1136-
return detail::d128_add_impl<decimal_fast128_t>(
1137-
sig_lhs, exp_lhs, (lhs < 0),
1138-
rhs.significand_, rhs.biased_exponent(), !rhs.sign_,
1139-
abs_lhs_bigger);
1120+
return -rhs + lhs;
11401121
}
11411122

11421123
constexpr auto operator*(const decimal_fast128_t& lhs, const decimal_fast128_t& rhs) noexcept -> decimal_fast128_t

0 commit comments

Comments
 (0)