NOTE: division by zero is UB and can be changed in future
| 642 | namespace NPrivateInt128 { |
| 643 | // NOTE: division by zero is UB and can be changed in future |
| 644 | constexpr void DivMod128(const ui128 lhs, const ui128 rhs, ui128* const quo, ui128* const rem) { |
| 645 | if (!quo && !rem) { |
| 646 | return; |
| 647 | } |
| 648 | |
| 649 | constexpr size_t n_udword_bits = sizeof(ui64) * CHAR_BIT; |
| 650 | constexpr size_t n_utword_bits = sizeof(ui128) * CHAR_BIT; |
| 651 | |
| 652 | ui128 q{}; |
| 653 | ui128 r{}; |
| 654 | |
| 655 | unsigned sr{}; |
| 656 | |
| 657 | /* special cases, X is unknown, K != 0 */ |
| 658 | if (GetHigh(lhs) == 0) |
| 659 | { |
| 660 | if (GetHigh(rhs) == 0) |
| 661 | { |
| 662 | /* 0 X |
| 663 | * --- |
| 664 | * 0 X |
| 665 | */ |
| 666 | if (rem) { |
| 667 | *rem = GetLow(lhs) % GetLow(rhs); |
| 668 | } |
| 669 | if (quo) { |
| 670 | *quo = GetLow(lhs) / GetLow(rhs); |
| 671 | } |
| 672 | return; |
| 673 | } |
| 674 | /* 0 X |
| 675 | * --- |
| 676 | * K X |
| 677 | */ |
| 678 | if (rem) { |
| 679 | *rem = GetLow(lhs); |
| 680 | } |
| 681 | if (quo) { |
| 682 | *quo = 0; |
| 683 | } |
| 684 | return; |
| 685 | } |
| 686 | /* n.s.high != 0 */ |
| 687 | if (GetLow(rhs) == 0) |
| 688 | { |
| 689 | if (GetHigh(rhs) == 0) |
| 690 | { |
| 691 | /* K X |
| 692 | * --- |
| 693 | * 0 0 |
| 694 | */ |
| 695 | if (rem) { |
| 696 | *rem = GetHigh(lhs) % GetLow(rhs); |
| 697 | } |
| 698 | if (quo) { |
| 699 | *quo = GetHigh(lhs) / GetLow(rhs); |
| 700 | } |
| 701 | return; |
no test coverage detected