MCPcopy Create free account
hub / github.com/apache/impala / Multiply

Method Multiply

be/src/runtime/decimal-value.inline.h:397–476  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

395template<typename T>
396template<typename RESULT_T>
397DecimalValue<RESULT_T> DecimalValue<T>::Multiply(int this_scale,
398 const DecimalValue& other, int other_scale, int result_precision, int result_scale,
399 bool round, bool* overflow) const {
400 // In the non-overflow case, we don't need to adjust by the scale since
401 // that is already handled by the FE when it computes the result decimal type.
402 // e.g. 1.23 * .2 (scale 2, scale 1 respectively) is identical to:
403 // 123 * 2 with a resulting scale 3. We can do the multiply on the unscaled values.
404 // The result scale in this case is the sum of the input scales.
405 RESULT_T x = value();
406 RESULT_T y = other.value();
407 if (x == 0 || y == 0) {
408 // Handle zero to avoid divide by zero in the overflow check below.
409 return DecimalValue<RESULT_T>(0);
410 }
411 RESULT_T result = 0;
412 bool needs_int256 = false;
413 int delta_scale = this_scale + other_scale - result_scale;
414 if (result_precision == ColumnType::MAX_PRECISION) {
415 DCHECK_EQ(sizeof(RESULT_T), 16);
416 int total_leading_zeros = BitUtil::CountLeadingZeros(abs(x)) +
417 BitUtil::CountLeadingZeros(abs(y));
418 // This check is quick, but conservative. In some cases it will indicate that
419 // converting to 256 bits is necessary, when it's not actually the case.
420 needs_int256 = total_leading_zeros <= 128;
421 if (UNLIKELY(needs_int256 && delta_scale == 0)) {
422 if (LIKELY(abs(x) > MAX_UNSCALED_DECIMAL16 / abs(y))) {
423 // If the intermediate value does not fit into 128 bits, we indicate overflow
424 // because the final value would also not fit into 128 bits since delta_scale is
425 // zero.
426 *overflow = true;
427 } else {
428 // We've verified that the intermediate (and final) value will fit into 128 bits.
429 needs_int256 = false;
430 }
431 }
432 }
433 if (UNLIKELY(needs_int256)) {
434 if (delta_scale == 0) {
435 DCHECK(*overflow);
436 } else {
437 int256_t intermediate_result = ConvertToInt256(x) * ConvertToInt256(y);
438 intermediate_result = DecimalUtil::ScaleDownAndRound<int256_t>(
439 intermediate_result, delta_scale, round);
440 result = ConvertToInt128(
441 intermediate_result, MAX_UNSCALED_DECIMAL16, overflow);
442 }
443 } else {
444 if (delta_scale == 0) {
445 result = DecimalUtil::SafeMultiply(x, y, false);
446 if (UNLIKELY(result_precision == ColumnType::MAX_PRECISION &&
447 abs(result) > MAX_UNSCALED_DECIMAL16)) {
448 // An overflow is possible here, if, for example, x = (2^64 - 1) and
449 // y = (2^63 - 1).
450 *overflow = true;
451 }
452 } else if (LIKELY(delta_scale <= 38)) {
453 result = DecimalUtil::SafeMultiply(x, y, false);
454 // The largest value that result can have here is (2^64 - 1) * (2^63 - 1), which is

Callers

nothing calls this directly

Calls 4

absFunction · 0.85
ConvertToInt256Function · 0.85
ConvertToInt128Function · 0.85
valueMethod · 0.45

Tested by

no test coverage detected