| 188 | |
| 189 | template<typename RESULT_T> |
| 190 | DecimalValue<RESULT_T> Add(const Decimal16Value& val, int this_scale, |
| 191 | const Decimal16Value& other, int other_scale, int result_precision, int result_scale, |
| 192 | bool* overflow) { |
| 193 | DCHECK_EQ(result_scale, std::max(this_scale, other_scale)); |
| 194 | RESULT_T x = 0; |
| 195 | RESULT_T y = 0; |
| 196 | *overflow |= AdjustToSameScale(val, this_scale, other, other_scale, |
| 197 | result_precision, &x, &y); |
| 198 | if (sizeof(RESULT_T) == 16) { |
| 199 | // Check overflow. |
| 200 | if (!*overflow && (val.value() < 0) == (other.value() < 0) && |
| 201 | result_precision == ColumnType::MAX_PRECISION) { |
| 202 | // Can only overflow if the signs are the same and result precision reaches |
| 203 | // max precision. |
| 204 | *overflow |= MAX_UNSCALED_DECIMAL16 - abs(x) < abs(y); |
| 205 | // TODO: faster to return here? We don't care at all about the perf on |
| 206 | // the overflow case but what makes the normal path faster? |
| 207 | } |
| 208 | } else { |
| 209 | DCHECK(!*overflow) << "Cannot overflow unless result is Decimal16Value"; |
| 210 | } |
| 211 | return DecimalValue<RESULT_T>(x + y); |
| 212 | } |
| 213 | |
| 214 | // set DISABLE_CHECK_OVERFLOW true will disable checking overflow. |
| 215 | #define TEST_ADD(NAME, FN, DISABLE_CHECK_OVERFLOW) \ |
no test coverage detected