162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci#define pr_fmt(fmt) "prime numbers: " fmt
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/module.h>
562306a36Sopenharmony_ci#include <linux/mutex.h>
662306a36Sopenharmony_ci#include <linux/prime_numbers.h>
762306a36Sopenharmony_ci#include <linux/slab.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#define bitmap_size(nbits) (BITS_TO_LONGS(nbits) * sizeof(unsigned long))
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cistruct primes {
1262306a36Sopenharmony_ci	struct rcu_head rcu;
1362306a36Sopenharmony_ci	unsigned long last, sz;
1462306a36Sopenharmony_ci	unsigned long primes[];
1562306a36Sopenharmony_ci};
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#if BITS_PER_LONG == 64
1862306a36Sopenharmony_cistatic const struct primes small_primes = {
1962306a36Sopenharmony_ci	.last = 61,
2062306a36Sopenharmony_ci	.sz = 64,
2162306a36Sopenharmony_ci	.primes = {
2262306a36Sopenharmony_ci		BIT(2) |
2362306a36Sopenharmony_ci		BIT(3) |
2462306a36Sopenharmony_ci		BIT(5) |
2562306a36Sopenharmony_ci		BIT(7) |
2662306a36Sopenharmony_ci		BIT(11) |
2762306a36Sopenharmony_ci		BIT(13) |
2862306a36Sopenharmony_ci		BIT(17) |
2962306a36Sopenharmony_ci		BIT(19) |
3062306a36Sopenharmony_ci		BIT(23) |
3162306a36Sopenharmony_ci		BIT(29) |
3262306a36Sopenharmony_ci		BIT(31) |
3362306a36Sopenharmony_ci		BIT(37) |
3462306a36Sopenharmony_ci		BIT(41) |
3562306a36Sopenharmony_ci		BIT(43) |
3662306a36Sopenharmony_ci		BIT(47) |
3762306a36Sopenharmony_ci		BIT(53) |
3862306a36Sopenharmony_ci		BIT(59) |
3962306a36Sopenharmony_ci		BIT(61)
4062306a36Sopenharmony_ci	}
4162306a36Sopenharmony_ci};
4262306a36Sopenharmony_ci#elif BITS_PER_LONG == 32
4362306a36Sopenharmony_cistatic const struct primes small_primes = {
4462306a36Sopenharmony_ci	.last = 31,
4562306a36Sopenharmony_ci	.sz = 32,
4662306a36Sopenharmony_ci	.primes = {
4762306a36Sopenharmony_ci		BIT(2) |
4862306a36Sopenharmony_ci		BIT(3) |
4962306a36Sopenharmony_ci		BIT(5) |
5062306a36Sopenharmony_ci		BIT(7) |
5162306a36Sopenharmony_ci		BIT(11) |
5262306a36Sopenharmony_ci		BIT(13) |
5362306a36Sopenharmony_ci		BIT(17) |
5462306a36Sopenharmony_ci		BIT(19) |
5562306a36Sopenharmony_ci		BIT(23) |
5662306a36Sopenharmony_ci		BIT(29) |
5762306a36Sopenharmony_ci		BIT(31)
5862306a36Sopenharmony_ci	}
5962306a36Sopenharmony_ci};
6062306a36Sopenharmony_ci#else
6162306a36Sopenharmony_ci#error "unhandled BITS_PER_LONG"
6262306a36Sopenharmony_ci#endif
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic DEFINE_MUTEX(lock);
6562306a36Sopenharmony_cistatic const struct primes __rcu *primes = RCU_INITIALIZER(&small_primes);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic unsigned long selftest_max;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic bool slow_is_prime_number(unsigned long x)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	unsigned long y = int_sqrt(x);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	while (y > 1) {
7462306a36Sopenharmony_ci		if ((x % y) == 0)
7562306a36Sopenharmony_ci			break;
7662306a36Sopenharmony_ci		y--;
7762306a36Sopenharmony_ci	}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	return y == 1;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic unsigned long slow_next_prime_number(unsigned long x)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	while (x < ULONG_MAX && !slow_is_prime_number(++x))
8562306a36Sopenharmony_ci		;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	return x;
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistatic unsigned long clear_multiples(unsigned long x,
9162306a36Sopenharmony_ci				     unsigned long *p,
9262306a36Sopenharmony_ci				     unsigned long start,
9362306a36Sopenharmony_ci				     unsigned long end)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	unsigned long m;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	m = 2 * x;
9862306a36Sopenharmony_ci	if (m < start)
9962306a36Sopenharmony_ci		m = roundup(start, x);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	while (m < end) {
10262306a36Sopenharmony_ci		__clear_bit(m, p);
10362306a36Sopenharmony_ci		m += x;
10462306a36Sopenharmony_ci	}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return x;
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic bool expand_to_next_prime(unsigned long x)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	const struct primes *p;
11262306a36Sopenharmony_ci	struct primes *new;
11362306a36Sopenharmony_ci	unsigned long sz, y;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	/* Betrand's Postulate (or Chebyshev's theorem) states that if n > 3,
11662306a36Sopenharmony_ci	 * there is always at least one prime p between n and 2n - 2.
11762306a36Sopenharmony_ci	 * Equivalently, if n > 1, then there is always at least one prime p
11862306a36Sopenharmony_ci	 * such that n < p < 2n.
11962306a36Sopenharmony_ci	 *
12062306a36Sopenharmony_ci	 * http://mathworld.wolfram.com/BertrandsPostulate.html
12162306a36Sopenharmony_ci	 * https://en.wikipedia.org/wiki/Bertrand's_postulate
12262306a36Sopenharmony_ci	 */
12362306a36Sopenharmony_ci	sz = 2 * x;
12462306a36Sopenharmony_ci	if (sz < x)
12562306a36Sopenharmony_ci		return false;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	sz = round_up(sz, BITS_PER_LONG);
12862306a36Sopenharmony_ci	new = kmalloc(sizeof(*new) + bitmap_size(sz),
12962306a36Sopenharmony_ci		      GFP_KERNEL | __GFP_NOWARN);
13062306a36Sopenharmony_ci	if (!new)
13162306a36Sopenharmony_ci		return false;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	mutex_lock(&lock);
13462306a36Sopenharmony_ci	p = rcu_dereference_protected(primes, lockdep_is_held(&lock));
13562306a36Sopenharmony_ci	if (x < p->last) {
13662306a36Sopenharmony_ci		kfree(new);
13762306a36Sopenharmony_ci		goto unlock;
13862306a36Sopenharmony_ci	}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	/* Where memory permits, track the primes using the
14162306a36Sopenharmony_ci	 * Sieve of Eratosthenes. The sieve is to remove all multiples of known
14262306a36Sopenharmony_ci	 * primes from the set, what remains in the set is therefore prime.
14362306a36Sopenharmony_ci	 */
14462306a36Sopenharmony_ci	bitmap_fill(new->primes, sz);
14562306a36Sopenharmony_ci	bitmap_copy(new->primes, p->primes, p->sz);
14662306a36Sopenharmony_ci	for (y = 2UL; y < sz; y = find_next_bit(new->primes, sz, y + 1))
14762306a36Sopenharmony_ci		new->last = clear_multiples(y, new->primes, p->sz, sz);
14862306a36Sopenharmony_ci	new->sz = sz;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	BUG_ON(new->last <= x);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	rcu_assign_pointer(primes, new);
15362306a36Sopenharmony_ci	if (p != &small_primes)
15462306a36Sopenharmony_ci		kfree_rcu((struct primes *)p, rcu);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ciunlock:
15762306a36Sopenharmony_ci	mutex_unlock(&lock);
15862306a36Sopenharmony_ci	return true;
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic void free_primes(void)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	const struct primes *p;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	mutex_lock(&lock);
16662306a36Sopenharmony_ci	p = rcu_dereference_protected(primes, lockdep_is_held(&lock));
16762306a36Sopenharmony_ci	if (p != &small_primes) {
16862306a36Sopenharmony_ci		rcu_assign_pointer(primes, &small_primes);
16962306a36Sopenharmony_ci		kfree_rcu((struct primes *)p, rcu);
17062306a36Sopenharmony_ci	}
17162306a36Sopenharmony_ci	mutex_unlock(&lock);
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci/**
17562306a36Sopenharmony_ci * next_prime_number - return the next prime number
17662306a36Sopenharmony_ci * @x: the starting point for searching to test
17762306a36Sopenharmony_ci *
17862306a36Sopenharmony_ci * A prime number is an integer greater than 1 that is only divisible by
17962306a36Sopenharmony_ci * itself and 1.  The set of prime numbers is computed using the Sieve of
18062306a36Sopenharmony_ci * Eratoshenes (on finding a prime, all multiples of that prime are removed
18162306a36Sopenharmony_ci * from the set) enabling a fast lookup of the next prime number larger than
18262306a36Sopenharmony_ci * @x. If the sieve fails (memory limitation), the search falls back to using
18362306a36Sopenharmony_ci * slow trial-divison, up to the value of ULONG_MAX (which is reported as the
18462306a36Sopenharmony_ci * final prime as a sentinel).
18562306a36Sopenharmony_ci *
18662306a36Sopenharmony_ci * Returns: the next prime number larger than @x
18762306a36Sopenharmony_ci */
18862306a36Sopenharmony_ciunsigned long next_prime_number(unsigned long x)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	const struct primes *p;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	rcu_read_lock();
19362306a36Sopenharmony_ci	p = rcu_dereference(primes);
19462306a36Sopenharmony_ci	while (x >= p->last) {
19562306a36Sopenharmony_ci		rcu_read_unlock();
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci		if (!expand_to_next_prime(x))
19862306a36Sopenharmony_ci			return slow_next_prime_number(x);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci		rcu_read_lock();
20162306a36Sopenharmony_ci		p = rcu_dereference(primes);
20262306a36Sopenharmony_ci	}
20362306a36Sopenharmony_ci	x = find_next_bit(p->primes, p->last, x + 1);
20462306a36Sopenharmony_ci	rcu_read_unlock();
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	return x;
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ciEXPORT_SYMBOL(next_prime_number);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci/**
21162306a36Sopenharmony_ci * is_prime_number - test whether the given number is prime
21262306a36Sopenharmony_ci * @x: the number to test
21362306a36Sopenharmony_ci *
21462306a36Sopenharmony_ci * A prime number is an integer greater than 1 that is only divisible by
21562306a36Sopenharmony_ci * itself and 1. Internally a cache of prime numbers is kept (to speed up
21662306a36Sopenharmony_ci * searching for sequential primes, see next_prime_number()), but if the number
21762306a36Sopenharmony_ci * falls outside of that cache, its primality is tested using trial-divison.
21862306a36Sopenharmony_ci *
21962306a36Sopenharmony_ci * Returns: true if @x is prime, false for composite numbers.
22062306a36Sopenharmony_ci */
22162306a36Sopenharmony_cibool is_prime_number(unsigned long x)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	const struct primes *p;
22462306a36Sopenharmony_ci	bool result;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	rcu_read_lock();
22762306a36Sopenharmony_ci	p = rcu_dereference(primes);
22862306a36Sopenharmony_ci	while (x >= p->sz) {
22962306a36Sopenharmony_ci		rcu_read_unlock();
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci		if (!expand_to_next_prime(x))
23262306a36Sopenharmony_ci			return slow_is_prime_number(x);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci		rcu_read_lock();
23562306a36Sopenharmony_ci		p = rcu_dereference(primes);
23662306a36Sopenharmony_ci	}
23762306a36Sopenharmony_ci	result = test_bit(x, p->primes);
23862306a36Sopenharmony_ci	rcu_read_unlock();
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	return result;
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ciEXPORT_SYMBOL(is_prime_number);
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_cistatic void dump_primes(void)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	const struct primes *p;
24762306a36Sopenharmony_ci	char *buf;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	rcu_read_lock();
25262306a36Sopenharmony_ci	p = rcu_dereference(primes);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	if (buf)
25562306a36Sopenharmony_ci		bitmap_print_to_pagebuf(true, buf, p->primes, p->sz);
25662306a36Sopenharmony_ci	pr_info("primes.{last=%lu, .sz=%lu, .primes[]=...x%lx} = %s\n",
25762306a36Sopenharmony_ci		p->last, p->sz, p->primes[BITS_TO_LONGS(p->sz) - 1], buf);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	rcu_read_unlock();
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	kfree(buf);
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistatic int selftest(unsigned long max)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	unsigned long x, last;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	if (!max)
26962306a36Sopenharmony_ci		return 0;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	for (last = 0, x = 2; x < max; x++) {
27262306a36Sopenharmony_ci		bool slow = slow_is_prime_number(x);
27362306a36Sopenharmony_ci		bool fast = is_prime_number(x);
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci		if (slow != fast) {
27662306a36Sopenharmony_ci			pr_err("inconsistent result for is-prime(%lu): slow=%s, fast=%s!\n",
27762306a36Sopenharmony_ci			       x, slow ? "yes" : "no", fast ? "yes" : "no");
27862306a36Sopenharmony_ci			goto err;
27962306a36Sopenharmony_ci		}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci		if (!slow)
28262306a36Sopenharmony_ci			continue;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci		if (next_prime_number(last) != x) {
28562306a36Sopenharmony_ci			pr_err("incorrect result for next-prime(%lu): expected %lu, got %lu\n",
28662306a36Sopenharmony_ci			       last, x, next_prime_number(last));
28762306a36Sopenharmony_ci			goto err;
28862306a36Sopenharmony_ci		}
28962306a36Sopenharmony_ci		last = x;
29062306a36Sopenharmony_ci	}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	pr_info("%s(%lu) passed, last prime was %lu\n", __func__, x, last);
29362306a36Sopenharmony_ci	return 0;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_cierr:
29662306a36Sopenharmony_ci	dump_primes();
29762306a36Sopenharmony_ci	return -EINVAL;
29862306a36Sopenharmony_ci}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cistatic int __init primes_init(void)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	return selftest(selftest_max);
30362306a36Sopenharmony_ci}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_cistatic void __exit primes_exit(void)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci	free_primes();
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_cimodule_init(primes_init);
31162306a36Sopenharmony_cimodule_exit(primes_exit);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_cimodule_param_named(selftest, selftest_max, ulong, 0400);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ciMODULE_AUTHOR("Intel Corporation");
31662306a36Sopenharmony_ciMODULE_LICENSE("GPL");
317