xref: /aosp_15_r20/external/igt-gpu-tools/lib/igt_primes.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
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