blob: 4a8b4dcc25624a405c268a44b67bb514e6956d24 [file] [log] [blame]
// Copyright 2014 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
#include "android/base/containers/HashUtils.h"
namespace android {
namespace base {
namespace internal {
namespace {
inline int hashCapacityCompare(size_t size, size_t shift) {
size_t capacity = 1U << shift;
// Essentially, one can rewrite:
// load < minLoad
// as:
// size / capacity < minLoad
// capacity * minLoad > size
if (capacity * kMinLoad > size * kLoadScale)
return +1;
// Similarly, one can rewrite:
// load > maxLoad
// as:
// size / capacity > maxLoad
// capacity * maxLoad < size
if (capacity * kMaxLoad < size * kLoadScale)
return -1;
return 0;
}
} // namespace
const int kPrimes[32] = {
1, /* For 1 << 0 */
2,
3,
7,
13,
31,
61,
127,
251,
509,
1021,
2039,
4093,
8191,
16381,
32749,
65521, /* For 1 << 16 */
131071,
262139,
524287,
1048573,
2097143,
4194301,
8388593,
16777213,
33554393,
67108859,
134217689,
268435399,
536870909,
1073741789,
2147483647 /* For 1 << 31 */
};
size_t hashShiftAdjust(size_t size, size_t shift) {
size_t newShift = shift;
int ret = hashCapacityCompare(size, shift);
if (ret < 0) {
// Capacity is too small and must be increased.
do {
if (newShift == kMaxShift) {
break;
}
++newShift;
} while (hashCapacityCompare(size, newShift) < 0);
} else if (ret > 0) {
// Capacity is too large and must be decreased.
do {
if (newShift == kMinShift) {
break;
}
newShift--;
} while (hashCapacityCompare(size, newShift) > 0);
}
return newShift;
}
} // namespace internal
} // namespace base
} // namespace android