MCPcopy Create free account
hub / github.com/numpy/numpy / libdivide_internal_u64_gen

Function libdivide_internal_u64_gen

numpy/core/include/numpy/libdivide/libdivide.h:712–762  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

710/////////// UINT64
711
712static inline struct libdivide_u64_t libdivide_internal_u64_gen(uint64_t d, int branchfree) {
713 if (d == 0) {
714 LIBDIVIDE_ERROR("divider must be != 0");
715 }
716
717 struct libdivide_u64_t result;
718 uint32_t floor_log_2_d = 63 - libdivide_count_leading_zeros64(d);
719
720 // Power of 2
721 if ((d & (d - 1)) == 0) {
722 // We need to subtract 1 from the shift value in case of an unsigned
723 // branchfree divider because there is a hardcoded right shift by 1
724 // in its division algorithm. Because of this we also need to add back
725 // 1 in its recovery algorithm.
726 result.magic = 0;
727 result.more = (uint8_t)(floor_log_2_d - (branchfree != 0));
728 } else {
729 uint64_t proposed_m, rem;
730 uint8_t more;
731 // (1 << (64 + floor_log_2_d)) / d
732 proposed_m = libdivide_128_div_64_to_64(1ULL << floor_log_2_d, 0, d, &rem);
733
734 LIBDIVIDE_ASSERT(rem > 0 && rem < d);
735 const uint64_t e = d - rem;
736
737 // This power works if e < 2**floor_log_2_d.
738 if (!branchfree && e < (1ULL << floor_log_2_d)) {
739 // This power works
740 more = floor_log_2_d;
741 } else {
742 // We have to use the general 65-bit algorithm. We need to compute
743 // (2**power) / d. However, we already have (2**(power-1))/d and
744 // its remainder. By doubling both, and then correcting the
745 // remainder, we can compute the larger division.
746 // don't care about overflow here - in fact, we expect it
747 proposed_m += proposed_m;
748 const uint64_t twice_rem = rem + rem;
749 if (twice_rem >= d || twice_rem < rem) proposed_m += 1;
750 more = floor_log_2_d | LIBDIVIDE_ADD_MARKER;
751 }
752 result.magic = 1 + proposed_m;
753 result.more = more;
754 // result.more's shift should in general be ceil_log_2_d. But if we
755 // used the smaller power, we subtract one from the shift because we're
756 // using the smaller power. If we're using the larger power, we
757 // subtract one from the shift because it's taken care of by the add
758 // indicator. So floor_log_2_d happens to be correct in both cases,
759 // which is why we do it outside of the if statement.
760 }
761 return result;
762}
763
764struct libdivide_u64_t libdivide_u64_gen(uint64_t d) {
765 return libdivide_internal_u64_gen(d, 0);

Callers 2

libdivide_u64_genFunction · 0.85

Calls 2

Tested by

no test coverage detected