18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "prime numbers: " fmt
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/module.h>
58c2ecf20Sopenharmony_ci#include <linux/mutex.h>
68c2ecf20Sopenharmony_ci#include <linux/prime_numbers.h>
78c2ecf20Sopenharmony_ci#include <linux/slab.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#define bitmap_size(nbits) (BITS_TO_LONGS(nbits) * sizeof(unsigned long))
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cistruct primes {
128c2ecf20Sopenharmony_ci	struct rcu_head rcu;
138c2ecf20Sopenharmony_ci	unsigned long last, sz;
148c2ecf20Sopenharmony_ci	unsigned long primes[];
158c2ecf20Sopenharmony_ci};
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#if BITS_PER_LONG == 64
188c2ecf20Sopenharmony_cistatic const struct primes small_primes = {
198c2ecf20Sopenharmony_ci	.last = 61,
208c2ecf20Sopenharmony_ci	.sz = 64,
218c2ecf20Sopenharmony_ci	.primes = {
228c2ecf20Sopenharmony_ci		BIT(2) |
238c2ecf20Sopenharmony_ci		BIT(3) |
248c2ecf20Sopenharmony_ci		BIT(5) |
258c2ecf20Sopenharmony_ci		BIT(7) |
268c2ecf20Sopenharmony_ci		BIT(11) |
278c2ecf20Sopenharmony_ci		BIT(13) |
288c2ecf20Sopenharmony_ci		BIT(17) |
298c2ecf20Sopenharmony_ci		BIT(19) |
308c2ecf20Sopenharmony_ci		BIT(23) |
318c2ecf20Sopenharmony_ci		BIT(29) |
328c2ecf20Sopenharmony_ci		BIT(31) |
338c2ecf20Sopenharmony_ci		BIT(37) |
348c2ecf20Sopenharmony_ci		BIT(41) |
358c2ecf20Sopenharmony_ci		BIT(43) |
368c2ecf20Sopenharmony_ci		BIT(47) |
378c2ecf20Sopenharmony_ci		BIT(53) |
388c2ecf20Sopenharmony_ci		BIT(59) |
398c2ecf20Sopenharmony_ci		BIT(61)
408c2ecf20Sopenharmony_ci	}
418c2ecf20Sopenharmony_ci};
428c2ecf20Sopenharmony_ci#elif BITS_PER_LONG == 32
438c2ecf20Sopenharmony_cistatic const struct primes small_primes = {
448c2ecf20Sopenharmony_ci	.last = 31,
458c2ecf20Sopenharmony_ci	.sz = 32,
468c2ecf20Sopenharmony_ci	.primes = {
478c2ecf20Sopenharmony_ci		BIT(2) |
488c2ecf20Sopenharmony_ci		BIT(3) |
498c2ecf20Sopenharmony_ci		BIT(5) |
508c2ecf20Sopenharmony_ci		BIT(7) |
518c2ecf20Sopenharmony_ci		BIT(11) |
528c2ecf20Sopenharmony_ci		BIT(13) |
538c2ecf20Sopenharmony_ci		BIT(17) |
548c2ecf20Sopenharmony_ci		BIT(19) |
558c2ecf20Sopenharmony_ci		BIT(23) |
568c2ecf20Sopenharmony_ci		BIT(29) |
578c2ecf20Sopenharmony_ci		BIT(31)
588c2ecf20Sopenharmony_ci	}
598c2ecf20Sopenharmony_ci};
608c2ecf20Sopenharmony_ci#else
618c2ecf20Sopenharmony_ci#error "unhandled BITS_PER_LONG"
628c2ecf20Sopenharmony_ci#endif
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(lock);
658c2ecf20Sopenharmony_cistatic const struct primes __rcu *primes = RCU_INITIALIZER(&small_primes);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic unsigned long selftest_max;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic bool slow_is_prime_number(unsigned long x)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	unsigned long y = int_sqrt(x);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	while (y > 1) {
748c2ecf20Sopenharmony_ci		if ((x % y) == 0)
758c2ecf20Sopenharmony_ci			break;
768c2ecf20Sopenharmony_ci		y--;
778c2ecf20Sopenharmony_ci	}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	return y == 1;
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic unsigned long slow_next_prime_number(unsigned long x)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	while (x < ULONG_MAX && !slow_is_prime_number(++x))
858c2ecf20Sopenharmony_ci		;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	return x;
888c2ecf20Sopenharmony_ci}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_cistatic unsigned long clear_multiples(unsigned long x,
918c2ecf20Sopenharmony_ci				     unsigned long *p,
928c2ecf20Sopenharmony_ci				     unsigned long start,
938c2ecf20Sopenharmony_ci				     unsigned long end)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	unsigned long m;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	m = 2 * x;
988c2ecf20Sopenharmony_ci	if (m < start)
998c2ecf20Sopenharmony_ci		m = roundup(start, x);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	while (m < end) {
1028c2ecf20Sopenharmony_ci		__clear_bit(m, p);
1038c2ecf20Sopenharmony_ci		m += x;
1048c2ecf20Sopenharmony_ci	}
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	return x;
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cistatic bool expand_to_next_prime(unsigned long x)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	const struct primes *p;
1128c2ecf20Sopenharmony_ci	struct primes *new;
1138c2ecf20Sopenharmony_ci	unsigned long sz, y;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	/* Betrand's Postulate (or Chebyshev's theorem) states that if n > 3,
1168c2ecf20Sopenharmony_ci	 * there is always at least one prime p between n and 2n - 2.
1178c2ecf20Sopenharmony_ci	 * Equivalently, if n > 1, then there is always at least one prime p
1188c2ecf20Sopenharmony_ci	 * such that n < p < 2n.
1198c2ecf20Sopenharmony_ci	 *
1208c2ecf20Sopenharmony_ci	 * http://mathworld.wolfram.com/BertrandsPostulate.html
1218c2ecf20Sopenharmony_ci	 * https://en.wikipedia.org/wiki/Bertrand's_postulate
1228c2ecf20Sopenharmony_ci	 */
1238c2ecf20Sopenharmony_ci	sz = 2 * x;
1248c2ecf20Sopenharmony_ci	if (sz < x)
1258c2ecf20Sopenharmony_ci		return false;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	sz = round_up(sz, BITS_PER_LONG);
1288c2ecf20Sopenharmony_ci	new = kmalloc(sizeof(*new) + bitmap_size(sz),
1298c2ecf20Sopenharmony_ci		      GFP_KERNEL | __GFP_NOWARN);
1308c2ecf20Sopenharmony_ci	if (!new)
1318c2ecf20Sopenharmony_ci		return false;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	mutex_lock(&lock);
1348c2ecf20Sopenharmony_ci	p = rcu_dereference_protected(primes, lockdep_is_held(&lock));
1358c2ecf20Sopenharmony_ci	if (x < p->last) {
1368c2ecf20Sopenharmony_ci		kfree(new);
1378c2ecf20Sopenharmony_ci		goto unlock;
1388c2ecf20Sopenharmony_ci	}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	/* Where memory permits, track the primes using the
1418c2ecf20Sopenharmony_ci	 * Sieve of Eratosthenes. The sieve is to remove all multiples of known
1428c2ecf20Sopenharmony_ci	 * primes from the set, what remains in the set is therefore prime.
1438c2ecf20Sopenharmony_ci	 */
1448c2ecf20Sopenharmony_ci	bitmap_fill(new->primes, sz);
1458c2ecf20Sopenharmony_ci	bitmap_copy(new->primes, p->primes, p->sz);
1468c2ecf20Sopenharmony_ci	for (y = 2UL; y < sz; y = find_next_bit(new->primes, sz, y + 1))
1478c2ecf20Sopenharmony_ci		new->last = clear_multiples(y, new->primes, p->sz, sz);
1488c2ecf20Sopenharmony_ci	new->sz = sz;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	BUG_ON(new->last <= x);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	rcu_assign_pointer(primes, new);
1538c2ecf20Sopenharmony_ci	if (p != &small_primes)
1548c2ecf20Sopenharmony_ci		kfree_rcu((struct primes *)p, rcu);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ciunlock:
1578c2ecf20Sopenharmony_ci	mutex_unlock(&lock);
1588c2ecf20Sopenharmony_ci	return true;
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic void free_primes(void)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	const struct primes *p;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	mutex_lock(&lock);
1668c2ecf20Sopenharmony_ci	p = rcu_dereference_protected(primes, lockdep_is_held(&lock));
1678c2ecf20Sopenharmony_ci	if (p != &small_primes) {
1688c2ecf20Sopenharmony_ci		rcu_assign_pointer(primes, &small_primes);
1698c2ecf20Sopenharmony_ci		kfree_rcu((struct primes *)p, rcu);
1708c2ecf20Sopenharmony_ci	}
1718c2ecf20Sopenharmony_ci	mutex_unlock(&lock);
1728c2ecf20Sopenharmony_ci}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci/**
1758c2ecf20Sopenharmony_ci * next_prime_number - return the next prime number
1768c2ecf20Sopenharmony_ci * @x: the starting point for searching to test
1778c2ecf20Sopenharmony_ci *
1788c2ecf20Sopenharmony_ci * A prime number is an integer greater than 1 that is only divisible by
1798c2ecf20Sopenharmony_ci * itself and 1.  The set of prime numbers is computed using the Sieve of
1808c2ecf20Sopenharmony_ci * Eratoshenes (on finding a prime, all multiples of that prime are removed
1818c2ecf20Sopenharmony_ci * from the set) enabling a fast lookup of the next prime number larger than
1828c2ecf20Sopenharmony_ci * @x. If the sieve fails (memory limitation), the search falls back to using
1838c2ecf20Sopenharmony_ci * slow trial-divison, up to the value of ULONG_MAX (which is reported as the
1848c2ecf20Sopenharmony_ci * final prime as a sentinel).
1858c2ecf20Sopenharmony_ci *
1868c2ecf20Sopenharmony_ci * Returns: the next prime number larger than @x
1878c2ecf20Sopenharmony_ci */
1888c2ecf20Sopenharmony_ciunsigned long next_prime_number(unsigned long x)
1898c2ecf20Sopenharmony_ci{
1908c2ecf20Sopenharmony_ci	const struct primes *p;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	rcu_read_lock();
1938c2ecf20Sopenharmony_ci	p = rcu_dereference(primes);
1948c2ecf20Sopenharmony_ci	while (x >= p->last) {
1958c2ecf20Sopenharmony_ci		rcu_read_unlock();
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci		if (!expand_to_next_prime(x))
1988c2ecf20Sopenharmony_ci			return slow_next_prime_number(x);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci		rcu_read_lock();
2018c2ecf20Sopenharmony_ci		p = rcu_dereference(primes);
2028c2ecf20Sopenharmony_ci	}
2038c2ecf20Sopenharmony_ci	x = find_next_bit(p->primes, p->last, x + 1);
2048c2ecf20Sopenharmony_ci	rcu_read_unlock();
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	return x;
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ciEXPORT_SYMBOL(next_prime_number);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci/**
2118c2ecf20Sopenharmony_ci * is_prime_number - test whether the given number is prime
2128c2ecf20Sopenharmony_ci * @x: the number to test
2138c2ecf20Sopenharmony_ci *
2148c2ecf20Sopenharmony_ci * A prime number is an integer greater than 1 that is only divisible by
2158c2ecf20Sopenharmony_ci * itself and 1. Internally a cache of prime numbers is kept (to speed up
2168c2ecf20Sopenharmony_ci * searching for sequential primes, see next_prime_number()), but if the number
2178c2ecf20Sopenharmony_ci * falls outside of that cache, its primality is tested using trial-divison.
2188c2ecf20Sopenharmony_ci *
2198c2ecf20Sopenharmony_ci * Returns: true if @x is prime, false for composite numbers.
2208c2ecf20Sopenharmony_ci */
2218c2ecf20Sopenharmony_cibool is_prime_number(unsigned long x)
2228c2ecf20Sopenharmony_ci{
2238c2ecf20Sopenharmony_ci	const struct primes *p;
2248c2ecf20Sopenharmony_ci	bool result;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	rcu_read_lock();
2278c2ecf20Sopenharmony_ci	p = rcu_dereference(primes);
2288c2ecf20Sopenharmony_ci	while (x >= p->sz) {
2298c2ecf20Sopenharmony_ci		rcu_read_unlock();
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci		if (!expand_to_next_prime(x))
2328c2ecf20Sopenharmony_ci			return slow_is_prime_number(x);
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci		rcu_read_lock();
2358c2ecf20Sopenharmony_ci		p = rcu_dereference(primes);
2368c2ecf20Sopenharmony_ci	}
2378c2ecf20Sopenharmony_ci	result = test_bit(x, p->primes);
2388c2ecf20Sopenharmony_ci	rcu_read_unlock();
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	return result;
2418c2ecf20Sopenharmony_ci}
2428c2ecf20Sopenharmony_ciEXPORT_SYMBOL(is_prime_number);
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_cistatic void dump_primes(void)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	const struct primes *p;
2478c2ecf20Sopenharmony_ci	char *buf;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	rcu_read_lock();
2528c2ecf20Sopenharmony_ci	p = rcu_dereference(primes);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	if (buf)
2558c2ecf20Sopenharmony_ci		bitmap_print_to_pagebuf(true, buf, p->primes, p->sz);
2568c2ecf20Sopenharmony_ci	pr_info("primes.{last=%lu, .sz=%lu, .primes[]=...x%lx} = %s\n",
2578c2ecf20Sopenharmony_ci		p->last, p->sz, p->primes[BITS_TO_LONGS(p->sz) - 1], buf);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	rcu_read_unlock();
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	kfree(buf);
2628c2ecf20Sopenharmony_ci}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_cistatic int selftest(unsigned long max)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	unsigned long x, last;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	if (!max)
2698c2ecf20Sopenharmony_ci		return 0;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	for (last = 0, x = 2; x < max; x++) {
2728c2ecf20Sopenharmony_ci		bool slow = slow_is_prime_number(x);
2738c2ecf20Sopenharmony_ci		bool fast = is_prime_number(x);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci		if (slow != fast) {
2768c2ecf20Sopenharmony_ci			pr_err("inconsistent result for is-prime(%lu): slow=%s, fast=%s!\n",
2778c2ecf20Sopenharmony_ci			       x, slow ? "yes" : "no", fast ? "yes" : "no");
2788c2ecf20Sopenharmony_ci			goto err;
2798c2ecf20Sopenharmony_ci		}
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci		if (!slow)
2828c2ecf20Sopenharmony_ci			continue;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci		if (next_prime_number(last) != x) {
2858c2ecf20Sopenharmony_ci			pr_err("incorrect result for next-prime(%lu): expected %lu, got %lu\n",
2868c2ecf20Sopenharmony_ci			       last, x, next_prime_number(last));
2878c2ecf20Sopenharmony_ci			goto err;
2888c2ecf20Sopenharmony_ci		}
2898c2ecf20Sopenharmony_ci		last = x;
2908c2ecf20Sopenharmony_ci	}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	pr_info("%s(%lu) passed, last prime was %lu\n", __func__, x, last);
2938c2ecf20Sopenharmony_ci	return 0;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_cierr:
2968c2ecf20Sopenharmony_ci	dump_primes();
2978c2ecf20Sopenharmony_ci	return -EINVAL;
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_cistatic int __init primes_init(void)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	return selftest(selftest_max);
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic void __exit primes_exit(void)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	free_primes();
3088c2ecf20Sopenharmony_ci}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_cimodule_init(primes_init);
3118c2ecf20Sopenharmony_cimodule_exit(primes_exit);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_cimodule_param_named(selftest, selftest_max, ulong, 0400);
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ciMODULE_AUTHOR("Intel Corporation");
3168c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
317