123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- #pragma once
- #include <util/system/compiler.h>
- #include <util/system/types.h>
- #if defined(_MSC_VER) && defined(_M_X64)
- #include <intrin.h>
- #endif
- Y_CONST_FUNCTION
- unsigned long HashBucketCount(unsigned long elementCount);
- namespace NPrivate {
-
-
- template <typename TDivisor, typename TDividend, typename MulUnsignedUpper>
- class TReciprocalDivisor {
- static_assert(sizeof(TDivisor) <= sizeof(TDividend), "TDivisor and TDividend should have the same size");
- public:
- constexpr TReciprocalDivisor() noexcept = default;
- constexpr TReciprocalDivisor(TDividend reciprocal, ui8 reciprocalShift, i8 hint, TDivisor divisor) noexcept
- : Reciprocal(reciprocal)
- , Divisor(divisor)
- , ReciprocalShift(reciprocalShift)
- , Hint(hint)
- {
- }
-
- Y_FORCE_INLINE TDividend Remainder(TDividend dividend) const noexcept {
- if (Y_UNLIKELY(Divisor == 1)) {
- return 0;
- }
- TDividend r = dividend - Quotent(dividend) * Divisor;
- return r;
- }
- Y_FORCE_INLINE TDivisor operator()() const noexcept {
- return Divisor;
- }
- Y_FORCE_INLINE static constexpr TReciprocalDivisor One() noexcept {
- return {1u, 0u, -1, 1u};
- }
- private:
-
- Y_FORCE_INLINE TDividend Quotent(TDividend dividend) const noexcept {
- const TDividend t = MulUnsignedUpper{}(dividend, Reciprocal);
- const TDividend q = (t + ((dividend - t) >> 1)) >> ReciprocalShift;
- return q;
- }
- public:
- TDividend Reciprocal = 0;
- TDivisor Divisor = 0;
- ui8 ReciprocalShift = 0;
- i8 Hint = 0;
- };
- template <typename T, typename TExtended, size_t shift>
- struct TMulUnsignedUpper {
-
- Y_FORCE_INLINE T operator()(T a, T b) const noexcept {
- return (static_cast<TExtended>(a) * static_cast<TExtended>(b)) >> shift;
- }
- };
- #if defined(_32_)
- using THashDivisor = ::NPrivate::TReciprocalDivisor<ui32, ui32, TMulUnsignedUpper<ui32, ui64, 32>>;
- #else
- #if defined(Y_HAVE_INT128)
- using THashDivisor = ::NPrivate::TReciprocalDivisor<ui32, ui64, TMulUnsignedUpper<ui64, unsigned __int128, 64>>;
- #elif defined(_MSC_VER) && defined(_M_X64)
- struct TMulUnsignedUpperVCIntrin {
-
- Y_FORCE_INLINE ui64 operator()(ui64 a, ui64 b) const noexcept {
- return __umulh(a, b);
- }
- };
- using THashDivisor = ::NPrivate::TReciprocalDivisor<ui32, ui64, TMulUnsignedUpperVCIntrin>;
- #else
- template <typename TDivisor, typename TDividend>
- class TNaiveDivisor {
- public:
- constexpr TNaiveDivisor() noexcept = default;
- constexpr TNaiveDivisor(TDivisor divisor) noexcept
- : Divisor(divisor)
- {
- }
- constexpr TNaiveDivisor(TDividend reciprocal, ui8 reciprocalShift, i8 hint, TDivisor divisor) noexcept
- : TNaiveDivisor(divisor)
- {
- Y_UNUSED(reciprocal);
- Y_UNUSED(reciprocalShift);
- Y_UNUSED(hint);
- }
- Y_FORCE_INLINE TDividend Remainder(TDividend dividend) const noexcept {
- return dividend % Divisor;
- }
- Y_FORCE_INLINE TDivisor operator()() const noexcept {
- return Divisor;
- }
- Y_FORCE_INLINE static constexpr TNaiveDivisor One() noexcept {
- return {1u};
- }
- public:
- TDivisor Divisor = 0;
- static constexpr i8 Hint = -1;
- };
- using THashDivisor = ::NPrivate::TNaiveDivisor<ui32, ui64>;
- #endif
- #endif
- }
- Y_CONST_FUNCTION
- ::NPrivate::THashDivisor HashBucketCountExt(unsigned long elementCount);
- Y_CONST_FUNCTION
- ::NPrivate::THashDivisor HashBucketCountExt(unsigned long elementCount, int hint);
|