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