SizePolicy.h 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #define UNKNOWN_MOD_INDEX 75 // count of the known mod array (under SizePolicy.cpp)
  7. struct PrimePolicy
  8. {
  9. inline static hash_t GetBucket(hash_t hashCode, uint size, int modFunctionIndex)
  10. {
  11. hash_t targetBucket = ModPrime(hashCode, size, modFunctionIndex);
  12. return targetBucket;
  13. }
  14. inline static uint GetSize(uint capacity, int *modFunctionIndex)
  15. {
  16. return GetPrime(capacity, modFunctionIndex);
  17. }
  18. private:
  19. static bool IsPrime(uint candidate);
  20. static uint GetPrime(uint min, int *modFunctionIndex);
  21. static hash_t ModPrime(hash_t key, uint prime, int modFunctionIndex);
  22. };
  23. struct PowerOf2Policy
  24. {
  25. inline static hash_t GetBucket(hash_t hashCode, uint size, int modFunctionIndex)
  26. {
  27. AssertMsg(Math::IsPow2(size) && size > 1, "Size is not a power of 2.");
  28. // we often deal with keys that differ in higher bits only, so smudge the entropy down a little
  29. // we do not need a perfect avalanche here, since this is for a hashtable lookup
  30. // the following is sufficient and reasonably cheap
  31. hashCode ^= (uint)hashCode >> 15;
  32. hashCode ^= (uint)hashCode >> 7;
  33. hash_t targetBucket = hashCode & (size-1);
  34. return targetBucket;
  35. }
  36. /// Returns a size that is power of 2 and
  37. /// greater than specified capacity.
  38. inline static uint GetSize(size_t minCapacity_t, int *modFunctionIndex)
  39. {
  40. AssertMsg(minCapacity_t <= MAXINT32, "the next higher power of 2 must fit in uint32");
  41. uint minCapacity = static_cast<uint>(minCapacity_t);
  42. *modFunctionIndex = UNKNOWN_MOD_INDEX;
  43. if(minCapacity <= 0)
  44. {
  45. return 4;
  46. }
  47. if (Math::IsPow2(minCapacity))
  48. {
  49. return minCapacity;
  50. }
  51. else
  52. {
  53. return 1 << (Math::Log2(minCapacity) + 1);
  54. }
  55. }
  56. };
  57. template <class SizePolicy, uint averageChainLength = 2, uint growthRateNumerator = 2, uint growthRateDenominator = 1, uint minBucket = 4>
  58. struct DictionarySizePolicy
  59. {
  60. CompileAssert(growthRateNumerator > growthRateDenominator);
  61. CompileAssert(growthRateDenominator != 0);
  62. inline static hash_t GetBucket(hash_t hashCode, uint bucketCount, int modFunctionIndex)
  63. {
  64. return SizePolicy::GetBucket(hashCode, bucketCount, modFunctionIndex);
  65. }
  66. inline static uint GetNextSize(uint minCapacity)
  67. {
  68. uint nextSize = minCapacity * growthRateNumerator / growthRateDenominator;
  69. return (growthRateDenominator != 1 && nextSize <= minCapacity)? minCapacity + 1 : nextSize;
  70. }
  71. inline static uint GetBucketSize(uint size, int *modFunctionIndex)
  72. {
  73. if (minBucket * averageChainLength >= size)
  74. {
  75. return SizePolicy::GetSize(minBucket, modFunctionIndex);
  76. }
  77. return SizePolicy::GetSize((size + (averageChainLength - 1)) / averageChainLength, modFunctionIndex);
  78. }
  79. };
  80. typedef DictionarySizePolicy<PrimePolicy> PrimeSizePolicy;
  81. typedef DictionarySizePolicy<PowerOf2Policy> PowerOf2SizePolicy;