| 393 | } |
| 394 | |
| 395 | BasicDecimal128 Mod(int64_t context, const BasicDecimalScalar128& x, |
| 396 | const BasicDecimalScalar128& y, int32_t out_precision, |
| 397 | int32_t out_scale, bool* overflow) { |
| 398 | if (y.value() == 0) { |
| 399 | const char* err_msg = "divide by zero error"; |
| 400 | gdv_fn_context_set_error_msg(context, err_msg); |
| 401 | return 0; |
| 402 | } |
| 403 | |
| 404 | // Adjust x and y to the same scale (higher one), and then, do a integer mod. |
| 405 | *overflow = false; |
| 406 | BasicDecimal128 result; |
| 407 | int32_t min_lz = MinLeadingZeros(x, y); |
| 408 | if (min_lz >= 2) { |
| 409 | auto higher_scale = std::max(x.scale(), y.scale()); |
| 410 | auto x_scaled = CheckAndIncreaseScale(x.value(), higher_scale - x.scale()); |
| 411 | auto y_scaled = CheckAndIncreaseScale(y.value(), higher_scale - y.scale()); |
| 412 | result = x_scaled % y_scaled; |
| 413 | DCHECK_LE(BasicDecimal128::Abs(result), BasicDecimal128::GetMaxValue()); |
| 414 | } else { |
| 415 | int64_t result_high; |
| 416 | uint64_t result_low; |
| 417 | |
| 418 | gdv_xlarge_mod(x.value().high_bits(), x.value().low_bits(), x.scale(), |
| 419 | y.value().high_bits(), y.value().low_bits(), y.scale(), &result_high, |
| 420 | &result_low); |
| 421 | result = BasicDecimal128(result_high, result_low); |
| 422 | } |
| 423 | DCHECK(BasicDecimal128::Abs(result) <= BasicDecimal128::Abs(x.value()) || |
| 424 | BasicDecimal128::Abs(result) <= BasicDecimal128::Abs(y.value())); |
| 425 | return result; |
| 426 | } |
| 427 | |
| 428 | int32_t CompareSameScale(const BasicDecimal128& x, const BasicDecimal128& y) { |
| 429 | if (x == y) { |