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

Function AddLarge

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

Adds numbers that are large enough so they can't be added directly. Both numbers must be either positive or zero.

Source from the content-addressed store, hash-verified

227// Adds numbers that are large enough so they can't be added directly. Both
228// numbers must be either positive or zero.
229inline int128_t AddLarge(int128_t x, int x_scale, int128_t y, int y_scale,
230 int result_scale, bool round, bool *overflow) {
231 DCHECK(x >= 0 && y >= 0);
232
233 int128_t left, right, x_left, x_right, y_left, y_right;
234 SeparateFractional(x, x_scale, y, y_scale, &x_left, &x_right, &y_left, &y_right);
235 DCHECK(x_left >= 0 && y_left >= 0 && x_right >= 0 && y_right >=0);
236
237 int max_scale = std::max(x_scale, y_scale);
238 int result_scale_decrease = max_scale - result_scale;
239 DCHECK(result_scale_decrease >= 0);
240
241 // carry_to_left should be 1 if there is an overflow when adding the fractional parts.
242 int carry_to_left = 0;
243 if (UNLIKELY(x_right >=
244 DecimalUtil::GetScaleMultiplier<int128_t>(max_scale) - y_right)) {
245 // Case where adding the fractional parts results in an overflow.
246 carry_to_left = 1;
247 right = x_right - DecimalUtil::GetScaleMultiplier<int128_t>(max_scale) + y_right;
248 } else {
249 // Case where adding the fractional parts does not result in an overflow.
250 right = x_right + y_right;
251 }
252 if (result_scale_decrease > 0) {
253 right = DecimalUtil::ScaleDownAndRound<int128_t>(
254 right, result_scale_decrease, round);
255 }
256 DCHECK(right >= 0);
257 // It is possible that right gets rounded up after scaling down (and it would look like
258 // it overflowed). We could handle this case by subtracting 10^result_scale from right
259 // (which would make it equal to zero) and adding one to carry_to_left, but
260 // it is not necessary, because doing that is equivalent to doing nothing.
261 DCHECK(right <= DecimalUtil::GetScaleMultiplier<int128_t>(result_scale));
262
263 *overflow |= x_left > MAX_UNSCALED_DECIMAL16 - y_left - carry_to_left;
264 left = ArithmeticUtil::AsUnsigned<std::plus>(
265 ArithmeticUtil::AsUnsigned<std::plus>(x_left, y_left),
266 static_cast<int128_t>(carry_to_left));
267
268 int128_t mult = DecimalUtil::GetScaleMultiplier<int128_t>(result_scale);
269 if (UNLIKELY(!*overflow &&
270 left > (MAX_UNSCALED_DECIMAL16 - right) / mult)) {
271 *overflow = true;
272 }
273 return ArithmeticUtil::AsUnsigned<std::plus>(
274 DecimalUtil::SafeMultiply(left, mult, *overflow), right);
275}
276
277// Subtracts numbers that are large enough so that we can't subtract directly. Neither
278// of the numbers can be zero and one must be positive and the other one negative.

Callers 1

AddMethod · 0.85

Calls 2

SeparateFractionalFunction · 0.85
maxFunction · 0.85

Tested by

no test coverage detected