mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-24 20:29:39 +08:00
Summary: A few places in the library seem to behave unexpectedly when the library is compiled or used with exceptions disabled. For example, not throwing an exception when a pointer is NULL can lead us to dereference the pointer later on, which is UB. This patch fixes such occurences. It's hard to tell whether there are other places where the no-exceptions mode misbehaves like this, because the replacement for throwing an exception does not always seem to be abort()ing, but at least this patch will improve the situation somewhat. See http://lists.llvm.org/pipermail/libcxx-dev/2019-January/000172.html Reviewers: mclow.lists, EricWF Subscribers: christof, jkorous, dexonsmith, libcxx-commits Differential Revision: https://reviews.llvm.org/D57761 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@353850 91177308-0d34-0410-b5e6-96231b3b80d8
562 lines
13 KiB
C++
562 lines
13 KiB
C++
//===-------------------------- hash.cpp ----------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "__hash_table"
|
|
#include "algorithm"
|
|
#include "stdexcept"
|
|
#include "type_traits"
|
|
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
|
|
#endif
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
namespace {
|
|
|
|
// handle all next_prime(i) for i in [1, 210), special case 0
|
|
const unsigned small_primes[] =
|
|
{
|
|
0,
|
|
2,
|
|
3,
|
|
5,
|
|
7,
|
|
11,
|
|
13,
|
|
17,
|
|
19,
|
|
23,
|
|
29,
|
|
31,
|
|
37,
|
|
41,
|
|
43,
|
|
47,
|
|
53,
|
|
59,
|
|
61,
|
|
67,
|
|
71,
|
|
73,
|
|
79,
|
|
83,
|
|
89,
|
|
97,
|
|
101,
|
|
103,
|
|
107,
|
|
109,
|
|
113,
|
|
127,
|
|
131,
|
|
137,
|
|
139,
|
|
149,
|
|
151,
|
|
157,
|
|
163,
|
|
167,
|
|
173,
|
|
179,
|
|
181,
|
|
191,
|
|
193,
|
|
197,
|
|
199,
|
|
211
|
|
};
|
|
|
|
// potential primes = 210*k + indices[i], k >= 1
|
|
// these numbers are not divisible by 2, 3, 5 or 7
|
|
// (or any integer 2 <= j <= 10 for that matter).
|
|
const unsigned indices[] =
|
|
{
|
|
1,
|
|
11,
|
|
13,
|
|
17,
|
|
19,
|
|
23,
|
|
29,
|
|
31,
|
|
37,
|
|
41,
|
|
43,
|
|
47,
|
|
53,
|
|
59,
|
|
61,
|
|
67,
|
|
71,
|
|
73,
|
|
79,
|
|
83,
|
|
89,
|
|
97,
|
|
101,
|
|
103,
|
|
107,
|
|
109,
|
|
113,
|
|
121,
|
|
127,
|
|
131,
|
|
137,
|
|
139,
|
|
143,
|
|
149,
|
|
151,
|
|
157,
|
|
163,
|
|
167,
|
|
169,
|
|
173,
|
|
179,
|
|
181,
|
|
187,
|
|
191,
|
|
193,
|
|
197,
|
|
199,
|
|
209
|
|
};
|
|
|
|
}
|
|
|
|
// Returns: If n == 0, returns 0. Else returns the lowest prime number that
|
|
// is greater than or equal to n.
|
|
//
|
|
// The algorithm creates a list of small primes, plus an open-ended list of
|
|
// potential primes. All prime numbers are potential prime numbers. However
|
|
// some potential prime numbers are not prime. In an ideal world, all potential
|
|
// prime numbers would be prime. Candidate prime numbers are chosen as the next
|
|
// highest potential prime. Then this number is tested for prime by dividing it
|
|
// by all potential prime numbers less than the sqrt of the candidate.
|
|
//
|
|
// This implementation defines potential primes as those numbers not divisible
|
|
// by 2, 3, 5, and 7. Other (common) implementations define potential primes
|
|
// as those not divisible by 2. A few other implementations define potential
|
|
// primes as those not divisible by 2 or 3. By raising the number of small
|
|
// primes which the potential prime is not divisible by, the set of potential
|
|
// primes more closely approximates the set of prime numbers. And thus there
|
|
// are fewer potential primes to search, and fewer potential primes to divide
|
|
// against.
|
|
|
|
template <size_t _Sz = sizeof(size_t)>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if<_Sz == 4, void>::type
|
|
__check_for_overflow(size_t N)
|
|
{
|
|
if (N > 0xFFFFFFFB)
|
|
__throw_overflow_error("__next_prime overflow");
|
|
}
|
|
|
|
template <size_t _Sz = sizeof(size_t)>
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
typename enable_if<_Sz == 8, void>::type
|
|
__check_for_overflow(size_t N)
|
|
{
|
|
if (N > 0xFFFFFFFFFFFFFFC5ull)
|
|
__throw_overflow_error("__next_prime overflow");
|
|
}
|
|
|
|
size_t
|
|
__next_prime(size_t n)
|
|
{
|
|
const size_t L = 210;
|
|
const size_t N = sizeof(small_primes) / sizeof(small_primes[0]);
|
|
// If n is small enough, search in small_primes
|
|
if (n <= small_primes[N-1])
|
|
return *std::lower_bound(small_primes, small_primes + N, n);
|
|
// Else n > largest small_primes
|
|
// Check for overflow
|
|
__check_for_overflow(n);
|
|
// Start searching list of potential primes: L * k0 + indices[in]
|
|
const size_t M = sizeof(indices) / sizeof(indices[0]);
|
|
// Select first potential prime >= n
|
|
// Known a-priori n >= L
|
|
size_t k0 = n / L;
|
|
size_t in = static_cast<size_t>(std::lower_bound(indices, indices + M, n - k0 * L)
|
|
- indices);
|
|
n = L * k0 + indices[in];
|
|
while (true)
|
|
{
|
|
// Divide n by all primes or potential primes (i) until:
|
|
// 1. The division is even, so try next potential prime.
|
|
// 2. The i > sqrt(n), in which case n is prime.
|
|
// It is known a-priori that n is not divisible by 2, 3, 5 or 7,
|
|
// so don't test those (j == 5 -> divide by 11 first). And the
|
|
// potential primes start with 211, so don't test against the last
|
|
// small prime.
|
|
for (size_t j = 5; j < N - 1; ++j)
|
|
{
|
|
const std::size_t p = small_primes[j];
|
|
const std::size_t q = n / p;
|
|
if (q < p)
|
|
return n;
|
|
if (n == q * p)
|
|
goto next;
|
|
}
|
|
// n wasn't divisible by small primes, try potential primes
|
|
{
|
|
size_t i = 211;
|
|
while (true)
|
|
{
|
|
std::size_t q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 10;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 8;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 8;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 6;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 4;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 2;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
i += 10;
|
|
q = n / i;
|
|
if (q < i)
|
|
return n;
|
|
if (n == q * i)
|
|
break;
|
|
|
|
// This will loop i to the next "plane" of potential primes
|
|
i += 2;
|
|
}
|
|
}
|
|
next:
|
|
// n is not prime. Increment n to next potential prime.
|
|
if (++in == M)
|
|
{
|
|
++k0;
|
|
in = 0;
|
|
}
|
|
n = L * k0 + indices[in];
|
|
}
|
|
}
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|