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

Method Add

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

Source from the content-addressed store, hash-verified

332template<typename T>
333template<typename RESULT_T>
334inline DecimalValue<RESULT_T> DecimalValue<T>::Add(int this_scale,
335 const DecimalValue& other, int other_scale, int result_precision, int result_scale,
336 bool round, bool* overflow) const {
337
338 if (sizeof(RESULT_T) < 16 || result_precision < 38) {
339 // The following check is guaranteed by the frontend.
340 DCHECK_EQ(result_scale, std::max(this_scale, other_scale));
341 RESULT_T x = 0;
342 RESULT_T y = 0;
343 AdjustToSameScale(*this, this_scale, other, other_scale, result_precision, &x, &y);
344 return DecimalValue<RESULT_T>(x + y);
345 }
346
347 // Compute how many leading zeros x and y would have after one of them gets scaled
348 // up to match the scale of the other one.
349 int min_lz = detail::MinLeadingZeros(
350 abs(value()), this_scale, abs(other.value()), other_scale);
351 int result_scale_decrease = std::max(
352 this_scale - result_scale, other_scale - result_scale);
353 DCHECK_GE(result_scale_decrease, 0);
354
355 const int MIN_LZ = 3;
356 if (min_lz >= MIN_LZ) {
357 // If both numbers have at least MIN_LZ leading zeros, we can add them directly
358 // without the risk of overflow.
359 // We want the result to have at least 2 leading zeros, which ensures that it fits
360 // into the maximum decimal because 2^126 - 1 < 10^38 - 1. If both x and y have at
361 // least 3 leading zeros, then we are guaranteed that the result will have at lest 2
362 // leading zeros.
363 RESULT_T x = 0;
364 RESULT_T y = 0;
365 AdjustToSameScale(*this, this_scale, other, other_scale, result_precision, &x, &y);
366 DCHECK(abs(x) <= MAX_UNSCALED_DECIMAL16 - abs(y));
367 x += y;
368 if (result_scale_decrease > 0) {
369 // After first adjusting x and y to the same scale and adding them together, we now
370 // need scale down the result to result_scale.
371 x = DecimalUtil::ScaleDownAndRound<RESULT_T>(x, result_scale_decrease, round);
372 }
373 return DecimalValue<RESULT_T>(x);
374 }
375
376 // If both numbers cannot be added directly, we have to resort to a more complex
377 // and slower algorithm.
378 int128_t x = value();
379 int128_t y = other.value();
380 int128_t result;
381
382 if (x >= 0 && y >= 0) {
383 result = detail::AddLarge(
384 x, this_scale, y, other_scale, result_scale, round, overflow);
385 } else if (x <= 0 && y <= 0) {
386 result = -detail::AddLarge(
387 -x, this_scale, -y, other_scale, result_scale, round, overflow);
388 } else {
389 result = detail::SubtractLarge(
390 x, this_scale, y, other_scale, result_scale, round, overflow);
391 }

Callers

nothing calls this directly

Calls 7

maxFunction · 0.85
AdjustToSameScaleFunction · 0.85
MinLeadingZerosFunction · 0.85
absFunction · 0.85
AddLargeFunction · 0.85
SubtractLargeFunction · 0.85
valueMethod · 0.45

Tested by

no test coverage detected