@@ -5,7 +5,8 @@ namespace
55using namespace clickhouse ;
66
77#ifdef ABSL_HAVE_INTRINSIC_INT128
8- inline bool addOverflow (const Int128 & l, const Int128 & r, Int128 * result)
8+ template <typename T>
9+ inline bool addOverflow (const Int128 & l, const T & r, Int128 * result)
910{
1011 __int128 res;
1112 const auto ret_value = __builtin_add_overflow (static_cast <__int128>(l), static_cast <__int128>(r), &res);
@@ -14,7 +15,8 @@ inline bool addOverflow(const Int128 & l, const Int128 & r, Int128 * result)
1415 return ret_value;
1516}
1617
17- inline bool mulOverflow (const Int128 & l, const Int128 & r, Int128 * result)
18+ template <typename T>
19+ inline bool mulOverflow (const Int128 & l, const T & r, Int128 * result)
1820{
1921 __int128 res;
2022 const auto ret_value = __builtin_mul_overflow (static_cast <__int128>(l), static_cast <__int128>(r), &res);
@@ -24,7 +26,13 @@ inline bool mulOverflow(const Int128 & l, const Int128 & r, Int128 * result)
2426}
2527
2628#else
27- inline bool getSign (const Int128 & v)
29+ template <typename T>
30+ inline bool getSignBit (const T & v)
31+ {
32+ return std::signbit (v);
33+ }
34+
35+ inline bool getSignBit (const Int128 & v)
2836{
2937// static constexpr Int128 zero {};
3038// return v < zero;
@@ -36,12 +44,12 @@ inline bool getSign(const Int128 & v)
3644inline bool addOverflow (const Int128 & l, const Int128 & r, Int128 * result)
3745{
3846 // *result = l + r;
39- // const auto result_sign = getSign (*result);
47+ // const auto result_sign = getSignBit (*result);
4048 // return l_sign == r_sign && l_sign != result_sign;
4149
4250 // Based on code from:
4351 // https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow#INT32C.Ensurethatoperationsonsignedintegersdonotresultinoverflow-CompliantSolution
44- const auto r_positive = !getSign (r);
52+ const auto r_positive = !getSignBit (r);
4553
4654 if ((r_positive && (l > (std::numeric_limits<Int128>::max () - r))) ||
4755 (!r_positive && (l < (std::numeric_limits<Int128>::min () - r)))) {
@@ -52,30 +60,31 @@ inline bool addOverflow(const Int128 & l, const Int128 & r, Int128 * result)
5260 return false ;
5361}
5462
55- inline bool mulOverflow (const Int128 & l, const Int128 & r, Int128 * result)
63+ template <typename T>
64+ inline bool mulOverflow (const Int128 & l, const T & r, Int128 * result)
5665{
5766 // Based on code from:
5867 // https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow#INT32C.Ensurethatoperationsonsignedintegersdonotresultinoverflow-CompliantSolution.3
59- const auto l_positive = !getSign (l);
60- const auto r_positive = !getSign (r);
68+ const auto l_positive = !getSignBit (l);
69+ const auto r_positive = !getSignBit (r);
6170
6271 if (l_positive) {
6372 if (r_positive) {
64- if (l > (std::numeric_limits<Int128>::max () / r)) {
73+ if (r != 0 && l > (std::numeric_limits<Int128>::max () / r)) {
6574 return true ;
6675 }
6776 } else {
68- if (r < (std::numeric_limits<Int128>::min () / l)) {
77+ if (l != 0 && r < (std::numeric_limits<Int128>::min () / l)) {
6978 return true ;
7079 }
7180 }
7281 } else {
7382 if (r_positive) {
74- if (l < (std::numeric_limits<Int128>::min () / r)) {
83+ if (r != 0 && l < (std::numeric_limits<Int128>::min () / r)) {
7584 return true ;
7685 }
7786 } else {
78- if ( ( l != 0 ) && (r < (std::numeric_limits<Int128>::max () / l))) {
87+ if (l != 0 && (r < (std::numeric_limits<Int128>::max () / l))) {
7988 return true ;
8089 }
8190 }
@@ -145,8 +154,8 @@ void ColumnDecimal::Append(const std::string& value) {
145154
146155 has_dot = true ;
147156 } else if (*c >= ' 0' && *c <= ' 9' ) {
148- if (mulOverflow (int_value, Int128 ( 10 ) , &int_value) ||
149- addOverflow (int_value, Int128 ( *c - ' 0' ) , &int_value)) {
157+ if (mulOverflow (int_value, 10 , &int_value) ||
158+ addOverflow (int_value, *c - ' 0' , &int_value)) {
150159 throw std::runtime_error (" value is too big for 128-bit integer" );
151160 }
152161 } else {
@@ -160,7 +169,7 @@ void ColumnDecimal::Append(const std::string& value) {
160169 }
161170
162171 while (zeros) {
163- if (mulOverflow (int_value, Int128 ( 10 ) , &int_value)) {
172+ if (mulOverflow (int_value, 10 , &int_value)) {
164173 throw std::runtime_error (" value is too big for 128-bit integer" );
165174 }
166175 --zeros;
0 commit comments