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

Method Divide

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

Source from the content-addressed store, hash-verified

478template<typename T>
479template<typename RESULT_T>
480inline DecimalValue<RESULT_T> DecimalValue<T>::Divide(int this_scale,
481 const DecimalValue& other, int other_scale, int result_precision, int result_scale,
482 bool round, bool* is_nan, bool* overflow) const {
483 DCHECK_GE(result_scale + other_scale, this_scale);
484 if (UNLIKELY(other.value() == 0)) {
485 // Divide by 0.
486 *is_nan = true;
487 return DecimalValue<RESULT_T>();
488 }
489 // We need to scale x up by the result scale and then do an integer divide.
490 // This truncates the result to the output scale.
491 int scale_by = result_scale + other_scale - this_scale;
492 DCHECK_GE(scale_by, 0);
493 // Use higher precision ints for intermediates to avoid overflows. Divides lead to
494 // large numbers very quickly (and get eliminated by the int divide).
495 if (sizeof(T) == 16) {
496 int128_t x_sp = value();
497 // There is a test in expr-test.cc that shows that it OK to check for overflow this
498 // way (and that no additional checks are required).
499 bool ovf = scale_by > 38 && detail::MaxBitsRequiredAfterScaling(x_sp, scale_by) > 255;
500 int256_t x = DecimalUtil::MultiplyByScale<int256_t>(
501 ConvertToInt256(x_sp), scale_by, ovf);
502 *overflow |= ovf;
503 int128_t y_sp = other.value();
504 int256_t y = ConvertToInt256(y_sp);
505 int128_t r = ConvertToInt128(x / y, MAX_UNSCALED_DECIMAL16, overflow);
506 if (round) {
507 int256_t remainder = x % y;
508 // The following is frought with apparent difficulty, as there is only 1 bit
509 // free in the implementation of int128_t representing our maximum value and
510 // doubling such a value would overflow in two's complement. However, we
511 // converted y to a 256 bit value, and remainder must be less than y, so there
512 // is plenty of space. Building a value to DCHECK for this is rather awkward, but
513 // quite obviously 2 * MAX_UNSCALED_DECIMAL16 has plenty of room in 256 bits.
514 // This will need to be fixed if we optimize to get back a 128-bit signed value.
515 if (abs(2 * remainder) >= abs(y)) {
516 // Bias at zero must be corrected by sign of divisor and dividend.
517 r += (Sign(x_sp) ^ Sign(y_sp)) + 1;
518 }
519 }
520 // Check overflow again after rounding since +/-1 could cause decimal overflow
521 if (result_precision == ColumnType::MAX_PRECISION) {
522 *overflow |= abs(r) > MAX_UNSCALED_DECIMAL16;
523 }
524 return DecimalValue<RESULT_T>(r);
525 } else {
526 int128_t x = DecimalUtil::MultiplyByScale<RESULT_T>(value(), scale_by, false);
527 int128_t y = other.value();
528 int128_t r = x / y;
529 if (round) {
530 int128_t remainder = x % y;
531 // No overflow because doubling the result of 8-byte integers fits in 128 bits
532 DCHECK_LT(sizeof(T), sizeof(remainder));
533 if (abs(2 * remainder) >= abs(y)) {
534 // No bias at zero. The result scale was chosen such that the smallest non-zero
535 // 'x' divided by the largest 'y' will always produce a non-zero result.
536 // If higher precision were required due to a very large scale, we would be
537 // computing in 256 bits, where getting a zero result is actually a posibility.

Callers

nothing calls this directly

Calls 6

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

Tested by

no test coverage detected