Adds numbers that are large enough so they can't be added directly. Both numbers must be either positive or zero.
| 227 | // Adds numbers that are large enough so they can't be added directly. Both |
| 228 | // numbers must be either positive or zero. |
| 229 | inline 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. |
no test coverage detected