1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker * Copyright © 2016 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker *
4*d83cc019SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker *
11*d83cc019SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker * Software.
14*d83cc019SAndroid Build Coastguard Worker *
15*d83cc019SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker */
23*d83cc019SAndroid Build Coastguard Worker
24*d83cc019SAndroid Build Coastguard Worker #include "igt_primes.h"
25*d83cc019SAndroid Build Coastguard Worker
26*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
27*d83cc019SAndroid Build Coastguard Worker #include <stdbool.h>
28*d83cc019SAndroid Build Coastguard Worker #include <string.h>
29*d83cc019SAndroid Build Coastguard Worker #include <math.h>
30*d83cc019SAndroid Build Coastguard Worker
31*d83cc019SAndroid Build Coastguard Worker /**
32*d83cc019SAndroid Build Coastguard Worker * SECTION:igt_primes
33*d83cc019SAndroid Build Coastguard Worker * @short_description: Prime numbers helper library
34*d83cc019SAndroid Build Coastguard Worker * @title: Primes
35*d83cc019SAndroid Build Coastguard Worker * @include: igt_primes.h
36*d83cc019SAndroid Build Coastguard Worker */
37*d83cc019SAndroid Build Coastguard Worker
38*d83cc019SAndroid Build Coastguard Worker #define BITS_PER_CHAR 8
39*d83cc019SAndroid Build Coastguard Worker #define BITS_PER_LONG (sizeof(long)*BITS_PER_CHAR)
40*d83cc019SAndroid Build Coastguard Worker
41*d83cc019SAndroid Build Coastguard Worker #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
42*d83cc019SAndroid Build Coastguard Worker #define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
43*d83cc019SAndroid Build Coastguard Worker
44*d83cc019SAndroid Build Coastguard Worker #define __round_mask(x, y) ((__typeof__(x))((y)-1))
45*d83cc019SAndroid Build Coastguard Worker #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
46*d83cc019SAndroid Build Coastguard Worker #define round_down(x, y) ((x) & ~__round_mask(x, y))
47*d83cc019SAndroid Build Coastguard Worker
48*d83cc019SAndroid Build Coastguard Worker #define min(x, y) ({ \
49*d83cc019SAndroid Build Coastguard Worker typeof(x) _min1 = (x); \
50*d83cc019SAndroid Build Coastguard Worker typeof(y) _min2 = (y); \
51*d83cc019SAndroid Build Coastguard Worker (void) (&_min1 == &_min2); \
52*d83cc019SAndroid Build Coastguard Worker _min1 < _min2 ? _min1 : _min2; \
53*d83cc019SAndroid Build Coastguard Worker })
54*d83cc019SAndroid Build Coastguard Worker
55*d83cc019SAndroid Build Coastguard Worker #define max(x, y) ({ \
56*d83cc019SAndroid Build Coastguard Worker typeof(x) _max1 = (x); \
57*d83cc019SAndroid Build Coastguard Worker typeof(y) _max2 = (y); \
58*d83cc019SAndroid Build Coastguard Worker (void) (&_max1 == &_max2); \
59*d83cc019SAndroid Build Coastguard Worker _max1 > _max2 ? _max1 : _max2; \
60*d83cc019SAndroid Build Coastguard Worker })
61*d83cc019SAndroid Build Coastguard Worker
__bit__(unsigned long nr)62*d83cc019SAndroid Build Coastguard Worker static inline unsigned long __bit__(unsigned long nr)
63*d83cc019SAndroid Build Coastguard Worker {
64*d83cc019SAndroid Build Coastguard Worker return 1UL << (nr % BITS_PER_LONG);
65*d83cc019SAndroid Build Coastguard Worker }
66*d83cc019SAndroid Build Coastguard Worker
set_bit(unsigned long nr,unsigned long * addr)67*d83cc019SAndroid Build Coastguard Worker static inline void set_bit(unsigned long nr, unsigned long *addr)
68*d83cc019SAndroid Build Coastguard Worker {
69*d83cc019SAndroid Build Coastguard Worker addr[nr / BITS_PER_LONG] |= __bit__(nr);
70*d83cc019SAndroid Build Coastguard Worker }
71*d83cc019SAndroid Build Coastguard Worker
clear_bit(unsigned long nr,unsigned long * addr)72*d83cc019SAndroid Build Coastguard Worker static inline void clear_bit(unsigned long nr, unsigned long *addr)
73*d83cc019SAndroid Build Coastguard Worker {
74*d83cc019SAndroid Build Coastguard Worker addr[nr / BITS_PER_LONG] &= ~__bit__(nr);
75*d83cc019SAndroid Build Coastguard Worker }
76*d83cc019SAndroid Build Coastguard Worker
test_bit(unsigned long nr,const unsigned long * addr)77*d83cc019SAndroid Build Coastguard Worker static inline bool test_bit(unsigned long nr, const unsigned long *addr)
78*d83cc019SAndroid Build Coastguard Worker {
79*d83cc019SAndroid Build Coastguard Worker return addr[nr / BITS_PER_LONG] & __bit__(nr);
80*d83cc019SAndroid Build Coastguard Worker }
81*d83cc019SAndroid Build Coastguard Worker
82*d83cc019SAndroid Build Coastguard Worker static unsigned long
__find_next_bit(const unsigned long * addr,unsigned long nbits,unsigned long start,unsigned long invert)83*d83cc019SAndroid Build Coastguard Worker __find_next_bit(const unsigned long *addr,
84*d83cc019SAndroid Build Coastguard Worker unsigned long nbits, unsigned long start,
85*d83cc019SAndroid Build Coastguard Worker unsigned long invert)
86*d83cc019SAndroid Build Coastguard Worker {
87*d83cc019SAndroid Build Coastguard Worker unsigned long tmp;
88*d83cc019SAndroid Build Coastguard Worker
89*d83cc019SAndroid Build Coastguard Worker if (!nbits || start >= nbits)
90*d83cc019SAndroid Build Coastguard Worker return nbits;
91*d83cc019SAndroid Build Coastguard Worker
92*d83cc019SAndroid Build Coastguard Worker tmp = addr[start / BITS_PER_LONG] ^ invert;
93*d83cc019SAndroid Build Coastguard Worker
94*d83cc019SAndroid Build Coastguard Worker /* Handle 1st word. */
95*d83cc019SAndroid Build Coastguard Worker tmp &= BITMAP_FIRST_WORD_MASK(start);
96*d83cc019SAndroid Build Coastguard Worker start = round_down(start, BITS_PER_LONG);
97*d83cc019SAndroid Build Coastguard Worker
98*d83cc019SAndroid Build Coastguard Worker while (!tmp) {
99*d83cc019SAndroid Build Coastguard Worker start += BITS_PER_LONG;
100*d83cc019SAndroid Build Coastguard Worker if (start >= nbits)
101*d83cc019SAndroid Build Coastguard Worker return nbits;
102*d83cc019SAndroid Build Coastguard Worker
103*d83cc019SAndroid Build Coastguard Worker tmp = addr[start / BITS_PER_LONG] ^ invert;
104*d83cc019SAndroid Build Coastguard Worker }
105*d83cc019SAndroid Build Coastguard Worker
106*d83cc019SAndroid Build Coastguard Worker return min(start + __builtin_ffsl(tmp) - 1, nbits);
107*d83cc019SAndroid Build Coastguard Worker }
108*d83cc019SAndroid Build Coastguard Worker
find_next_bit(const unsigned long * addr,unsigned long size,unsigned long offset)109*d83cc019SAndroid Build Coastguard Worker static unsigned long find_next_bit(const unsigned long *addr,
110*d83cc019SAndroid Build Coastguard Worker unsigned long size,
111*d83cc019SAndroid Build Coastguard Worker unsigned long offset)
112*d83cc019SAndroid Build Coastguard Worker {
113*d83cc019SAndroid Build Coastguard Worker return __find_next_bit(addr, size, offset, 0UL);
114*d83cc019SAndroid Build Coastguard Worker }
115*d83cc019SAndroid Build Coastguard Worker
slow_next_prime_number(unsigned long x)116*d83cc019SAndroid Build Coastguard Worker static unsigned long slow_next_prime_number(unsigned long x)
117*d83cc019SAndroid Build Coastguard Worker {
118*d83cc019SAndroid Build Coastguard Worker for (;;) {
119*d83cc019SAndroid Build Coastguard Worker unsigned long y = sqrt(++x) + 1;
120*d83cc019SAndroid Build Coastguard Worker while (y > 1) {
121*d83cc019SAndroid Build Coastguard Worker if ((x % y) == 0)
122*d83cc019SAndroid Build Coastguard Worker break;
123*d83cc019SAndroid Build Coastguard Worker y--;
124*d83cc019SAndroid Build Coastguard Worker }
125*d83cc019SAndroid Build Coastguard Worker if (y == 1)
126*d83cc019SAndroid Build Coastguard Worker return x;
127*d83cc019SAndroid Build Coastguard Worker }
128*d83cc019SAndroid Build Coastguard Worker }
129*d83cc019SAndroid Build Coastguard Worker
mark_multiples(unsigned long x,unsigned long * primes,unsigned long start,unsigned long end)130*d83cc019SAndroid Build Coastguard Worker static unsigned long mark_multiples(unsigned long x,
131*d83cc019SAndroid Build Coastguard Worker unsigned long *primes,
132*d83cc019SAndroid Build Coastguard Worker unsigned long start,
133*d83cc019SAndroid Build Coastguard Worker unsigned long end)
134*d83cc019SAndroid Build Coastguard Worker {
135*d83cc019SAndroid Build Coastguard Worker unsigned long m;
136*d83cc019SAndroid Build Coastguard Worker
137*d83cc019SAndroid Build Coastguard Worker m = 2*x;
138*d83cc019SAndroid Build Coastguard Worker if (m < start)
139*d83cc019SAndroid Build Coastguard Worker m = (start / x + 1) * x;
140*d83cc019SAndroid Build Coastguard Worker
141*d83cc019SAndroid Build Coastguard Worker while (m < end) {
142*d83cc019SAndroid Build Coastguard Worker clear_bit(m, primes);
143*d83cc019SAndroid Build Coastguard Worker m += x;
144*d83cc019SAndroid Build Coastguard Worker }
145*d83cc019SAndroid Build Coastguard Worker
146*d83cc019SAndroid Build Coastguard Worker return x;
147*d83cc019SAndroid Build Coastguard Worker }
148*d83cc019SAndroid Build Coastguard Worker
igt_next_prime_number(unsigned long x)149*d83cc019SAndroid Build Coastguard Worker unsigned long igt_next_prime_number(unsigned long x)
150*d83cc019SAndroid Build Coastguard Worker {
151*d83cc019SAndroid Build Coastguard Worker static unsigned long *primes;
152*d83cc019SAndroid Build Coastguard Worker static unsigned long last, last_sz;
153*d83cc019SAndroid Build Coastguard Worker
154*d83cc019SAndroid Build Coastguard Worker if (x == 0)
155*d83cc019SAndroid Build Coastguard Worker return 1; /* a white lie for for_each_prime_number() */
156*d83cc019SAndroid Build Coastguard Worker if (x == 1)
157*d83cc019SAndroid Build Coastguard Worker return 2;
158*d83cc019SAndroid Build Coastguard Worker
159*d83cc019SAndroid Build Coastguard Worker if (x >= last) {
160*d83cc019SAndroid Build Coastguard Worker unsigned long sz, y;
161*d83cc019SAndroid Build Coastguard Worker unsigned long *nprimes;
162*d83cc019SAndroid Build Coastguard Worker
163*d83cc019SAndroid Build Coastguard Worker sz = x*x;
164*d83cc019SAndroid Build Coastguard Worker if (sz < x)
165*d83cc019SAndroid Build Coastguard Worker return slow_next_prime_number(x);
166*d83cc019SAndroid Build Coastguard Worker
167*d83cc019SAndroid Build Coastguard Worker sz = round_up(sz, BITS_PER_LONG);
168*d83cc019SAndroid Build Coastguard Worker nprimes = realloc(primes, sz / sizeof(long));
169*d83cc019SAndroid Build Coastguard Worker if (!nprimes)
170*d83cc019SAndroid Build Coastguard Worker return slow_next_prime_number(x);
171*d83cc019SAndroid Build Coastguard Worker
172*d83cc019SAndroid Build Coastguard Worker /* Where memory permits, track the primes using the
173*d83cc019SAndroid Build Coastguard Worker * Sieve of Eratosthenes.
174*d83cc019SAndroid Build Coastguard Worker */
175*d83cc019SAndroid Build Coastguard Worker memset(nprimes + last_sz / BITS_PER_LONG,
176*d83cc019SAndroid Build Coastguard Worker 0xff, (sz - last_sz) / sizeof(long));
177*d83cc019SAndroid Build Coastguard Worker for (y = 2UL; y < sz; y = find_next_bit(nprimes, sz, y + 1))
178*d83cc019SAndroid Build Coastguard Worker last = mark_multiples(y, nprimes, last_sz, sz);
179*d83cc019SAndroid Build Coastguard Worker
180*d83cc019SAndroid Build Coastguard Worker primes = nprimes;
181*d83cc019SAndroid Build Coastguard Worker last_sz = sz;
182*d83cc019SAndroid Build Coastguard Worker }
183*d83cc019SAndroid Build Coastguard Worker
184*d83cc019SAndroid Build Coastguard Worker return find_next_bit(primes, last, x + 1);
185*d83cc019SAndroid Build Coastguard Worker }
186