| 553 | ////////// UINT32 |
| 554 | |
| 555 | static inline struct libdivide_u32_t libdivide_internal_u32_gen(uint32_t d, int branchfree) { |
| 556 | if (d == 0) { |
| 557 | LIBDIVIDE_ERROR("divider must be != 0"); |
| 558 | } |
| 559 | |
| 560 | struct libdivide_u32_t result; |
| 561 | uint32_t floor_log_2_d = 31 - libdivide_count_leading_zeros32(d); |
| 562 | |
| 563 | // Power of 2 |
| 564 | if ((d & (d - 1)) == 0) { |
| 565 | // We need to subtract 1 from the shift value in case of an unsigned |
| 566 | // branchfree divider because there is a hardcoded right shift by 1 |
| 567 | // in its division algorithm. Because of this we also need to add back |
| 568 | // 1 in its recovery algorithm. |
| 569 | result.magic = 0; |
| 570 | result.more = (uint8_t)(floor_log_2_d - (branchfree != 0)); |
| 571 | } else { |
| 572 | uint8_t more; |
| 573 | uint32_t rem, proposed_m; |
| 574 | proposed_m = libdivide_64_div_32_to_32(1U << floor_log_2_d, 0, d, &rem); |
| 575 | |
| 576 | LIBDIVIDE_ASSERT(rem > 0 && rem < d); |
| 577 | const uint32_t e = d - rem; |
| 578 | |
| 579 | // This power works if e < 2**floor_log_2_d. |
| 580 | if (!branchfree && (e < (1U << floor_log_2_d))) { |
| 581 | // This power works |
| 582 | more = floor_log_2_d; |
| 583 | } else { |
| 584 | // We have to use the general 33-bit algorithm. We need to compute |
| 585 | // (2**power) / d. However, we already have (2**(power-1))/d and |
| 586 | // its remainder. By doubling both, and then correcting the |
| 587 | // remainder, we can compute the larger division. |
| 588 | // don't care about overflow here - in fact, we expect it |
| 589 | proposed_m += proposed_m; |
| 590 | const uint32_t twice_rem = rem + rem; |
| 591 | if (twice_rem >= d || twice_rem < rem) proposed_m += 1; |
| 592 | more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; |
| 593 | } |
| 594 | result.magic = 1 + proposed_m; |
| 595 | result.more = more; |
| 596 | // result.more's shift should in general be ceil_log_2_d. But if we |
| 597 | // used the smaller power, we subtract one from the shift because we're |
| 598 | // using the smaller power. If we're using the larger power, we |
| 599 | // subtract one from the shift because it's taken care of by the add |
| 600 | // indicator. So floor_log_2_d happens to be correct in both cases. |
| 601 | } |
| 602 | return result; |
| 603 | } |
| 604 | |
| 605 | struct libdivide_u32_t libdivide_u32_gen(uint32_t d) { |
| 606 | return libdivide_internal_u32_gen(d, 0); |
no test coverage detected