File Coverage

sieve.h
Criterion Covered Total %
statement 4 4 100.0
branch 4 4 100.0
condition n/a
subroutine n/a
pod n/a
total 8 8 100.0


line stmt bran cond sub pod time code
1             #ifndef MPU_SIEVE_H
2             #define MPU_SIEVE_H
3              
4             #include "ptypes.h"
5             #define FUNC_ctz 1
6             #include "util.h"
7              
8             extern unsigned char* sieve_erat30(UV end);
9             extern bool sieve_segment_partial(unsigned char* mem, UV startd, UV endd, UV depth);
10             extern bool sieve_segment(unsigned char* mem, UV startd, UV endd);
11             extern void* start_segment_primes(UV low, UV high, unsigned char** segmentmem);
12             extern bool next_segment_primes(void* vctx, UV* base, UV* low, UV* high);
13             extern void end_segment_primes(void* vctx);
14              
15             /* Generate primes P[0] = 2, P[1] = 3, P[2] = 5, .... */
16             extern UV range_prime_sieve(UV** list, UV lo, UV hi);
17              
18             /* Generate 32-bit primes up to n.
19             * The first entries will be zero, followed by 2, 3, 5, 7, 11, ...
20             * Returns the count of primes created, irrespective of the offset.
21             * Hence, the last prime will be in P[offset+count-1].
22             */
23             extern uint32_t range_prime_sieve_32(uint32_t** list, uint32_t n, uint32_t offset);
24              
25              
26              
27              
28             static const unsigned char wheel30[] = {1, 7, 11, 13, 17, 19, 23, 29};
29             /* Used for moving between primes */
30             static const unsigned char nextwheel30[30] = {
31             1, 7, 7, 7, 7, 7, 7, 11, 11, 11, 11, 13, 13, 17, 17,
32             17, 17, 19, 19, 23, 23, 23, 23, 29, 29, 29, 29, 29, 29, 1 };
33             static const unsigned char prevwheel30[30] = {
34             29, 29, 1, 1, 1, 1, 1, 1, 7, 7, 7, 7, 11, 11, 13,
35             13, 13, 13, 17, 17, 19, 19, 19, 19, 23, 23, 23, 23, 23, 23 };
36             /* The bit mask within a byte */
37             static const unsigned char masktab30[30] = {
38             0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 4, 0, 8, 0,
39             0, 0, 16, 0, 32, 0, 0, 0, 64, 0, 0, 0, 0, 0,128 };
40             /* Inverse of masktab30 */
41             static const unsigned char imask30[129] = {
42             0,1,7,0,11,0,0,0,13,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,
43             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,23,
44             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
45             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29};
46             /* Add this to a number and you'll ensure you're on a wheel location */
47             static const unsigned char distancewheel30[30] =
48             {1,0,5,4,3,2,1,0,3,2,1,0,1,0,3,2,1,0,1,0,3,2,1,0,5,4,3,2,1,0};
49             /* add this to n to get to the next wheel location */
50             static const unsigned char wheeladvance30[30] =
51             {1,6,5,4,3,2,1,4,3,2,1,2,1,4,3,2,1,2,1,4,3,2,1,6,5,4,3,2,1,2};
52             /* subtract this from n to get to the previous wheel location */
53             static const unsigned char wheelretreat30[30] =
54             {1,2,1,2,3,4,5,6,1,2,3,4,1,2,1,2,3,4,1,2,1,2,3,4,1,2,3,4,5,6};
55             /* Given a sieve byte, this indicates the first zero */
56             static const unsigned char nextzero30[256] =
57             {0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,
58             0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,
59             0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,
60             0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,
61             0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,
62             0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,
63             0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8};
64             /* At this m (p-30*(p/30)), OR with this to clear previous entries */
65             static const unsigned char clearprev30[30] =
66             { 0, 0, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 7, 7, 15,
67             15, 15, 15, 31, 31, 63, 63, 63, 63,127,127,127,127,127,127};
68              
69              
70             #ifdef FUNC_is_prime_in_sieve
71 138899           static bool is_prime_in_sieve(const unsigned char* sieve, UV p) {
72 138899           UV d = p/30;
73 138899           UV m = p - d*30;
74             /* If m isn't part of the wheel, we return 0 */
75 138899 100         return ( (masktab30[m] != 0) && ((sieve[d] & masktab30[m]) == 0) );
    100          
76             }
77             #endif
78              
79             #ifdef FUNC_next_prime_in_sieve
80             /* Will return 0 if it goes past lastp */
81             static UV next_prime_in_sieve(const unsigned char* sieve, UV p, UV lastp) {
82             UV d, m;
83             unsigned char s;
84             if (p < 7)
85             return (p < 2) ? 2 : (p < 3) ? 3 : (p < 5) ? 5 : 7;
86             p++;
87             if (p >= lastp) return 0;
88             d = p/30;
89             m = p - d*30;
90             s = sieve[d] | clearprev30[m];
91             while (s == 0xFF) {
92             d++;
93             if (d*30 >= lastp) return 0;
94             s = sieve[d];
95             }
96             return d*30 + wheel30[nextzero30[s]];
97             }
98             #endif
99             #ifdef FUNC_prev_prime_in_sieve
100             static UV prev_prime_in_sieve(const unsigned char* sieve, UV p) {
101             UV d, m;
102             if (p <= 7)
103             return (p <= 2) ? 0 : (p <= 3) ? 2 : (p <= 5) ? 3 : 5;
104             d = p/30;
105             m = p - d*30;
106             do {
107             m = prevwheel30[m];
108             if (m==29) { if (d == 0) return 0; d--; }
109             } while (sieve[d] & masktab30[m]);
110             return(d*30+m);
111             }
112             #endif
113              
114             #if 0
115             /* Useful macros for the wheel-30 sieve array */
116             #define START_DO_FOR_EACH_SIEVE_PRIME(sieve, base, a, b) \
117             { \
118             const unsigned char* sieve_ = sieve; \
119             UV base_ = base; \
120             UV p = a-base_; \
121             UV l_ = b; \
122             UV d_ = p/30; \
123             UV lastd_ = (l_-base_)/30; \
124             unsigned char bit_, s_ = sieve_[d_] | clearprev30[p-d_*30]; \
125             base_ += d_*30; \
126             while (1) { \
127             if (s_ == 0xFF) { \
128             do { \
129             base_ += 30; d_++; \
130             if (d_ > lastd_) break; \
131             s_ = sieve_[d_]; \
132             } while (s_ == 0xFF); \
133             if (d_ > lastd_) break; \
134             } \
135             bit_ = nextzero30[s_]; \
136             s_ |= 1 << bit_; \
137             p = base_ + wheel30[bit_]; \
138             if (p > l_ || p < base_) break; /* handle overflow */ \
139             {
140              
141             #define END_DO_FOR_EACH_SIEVE_PRIME \
142             } \
143             } \
144             }
145             #else
146             /* Extract word at a time, good suggestion from Kim Walisch */
147             static const unsigned char wheel240[] = {1,7,11,13,17,19,23,29,31,37,41,43,47,49,53,59,61,67,71,73,77,79,83,89,91,97,101,103,107,109,113,119,121,127,131,133,137,139,143,149,151,157,161,163,167,169,173,179,181,187,191,193,197,199,203,209,211,217,221,223,227,229,233,239};
148             #define START_DO_FOR_EACH_SIEVE_PRIME(sieve, base, a, b) \
149             { \
150             const UV* sieve_ = (const UV*)sieve; /* word ptr to sieve */ \
151             const UV nperw_ = 30*sizeof(UV); /* nums per word */ \
152             UV base_ = base; /* start of sieve n */ \
153             UV b_ = a; /* begin value n */ \
154             UV f_ = b; /* final value n */ \
155             UV begw_ = (b_-base_)/nperw_; /* first word */ \
156             UV endw_ = (f_-base_)/nperw_; /* last word */ \
157             UV sw_, tz_, p; \
158             base_ += begw_*nperw_; \
159             while (begw_ <= endw_) { \
160             sw_ = ~ LEUV(sieve_[begw_]); \
161             while (sw_ != 0) { \
162             tz_ = ctz(sw_); \
163             sw_ &= ~(UVCONST(1) << tz_); \
164             p = base_ + wheel240[tz_]; \
165             if (p > f_) break; \
166             if (p >= b_) {
167              
168             #define END_DO_FOR_EACH_SIEVE_PRIME \
169             } \
170             } \
171             begw_++; \
172             base_ += nperw_; \
173             } \
174             }
175             #endif
176              
177             #define START_DO_FOR_EACH_PRIME(a, b) \
178             { \
179             const unsigned char* sieve_; \
180             UV p = a; \
181             UV l_ = b; \
182             UV d_ = p/30; \
183             UV lastd_ = l_/30; \
184             unsigned char s_, bit_; \
185             get_prime_cache(l_, &sieve_); \
186             if (p > 1 && p < 7) p--; \
187             s_ = sieve_[d_] | clearprev30[p-d_*30]; \
188             while (1) { \
189             if (p < 5) { \
190             p = (p < 2) ? 2 : (p < 3) ? 3 : 5; \
191             } else { \
192             if (s_ == 0xFF) { \
193             do { \
194             d_++; \
195             if (d_ > lastd_) break; \
196             s_ = sieve_[d_]; \
197             } while (s_ == 0xFF); \
198             if (d_ > lastd_) break; \
199             } \
200             bit_ = nextzero30[s_]; \
201             s_ |= 1 << bit_; \
202             p = d_*30 + wheel30[bit_]; \
203             if (p < d_*30) break; \
204             } \
205             if (p > l_) break; \
206             { \
207              
208             #define RETURN_FROM_EACH_PRIME(retstmt) \
209             do { release_prime_cache(sieve_); retstmt; } while (0)
210              
211             #define END_DO_FOR_EACH_PRIME \
212             } \
213             } \
214             release_prime_cache(sieve_); \
215             }
216              
217              
218             #define SIMPLE_FOR_EACH_PRIME(a, b) \
219             { \
220             UV p_ = a; \
221             UV l_ = b; \
222             if (p_ > 0) p_--; \
223             while (1) { \
224             UV p = (p_ = next_prime(p_)); \
225             if (p > l_ || p == 0) break; \
226             { \
227              
228             #define END_SIMPLE_FOR_EACH_PRIME \
229             } \
230             } \
231             }
232              
233             /* Mark at , but if that is less than , then use the first multiple
234             * of

at or after lo.

235             *
236             * I.e. the result n is n = p2 + k*p >= lo with the smallest possible k.
237             * TODO: this assumes first is a multiple of p. Fix. */
238             #define P_GT_LO(first,p,lo) ( ((first)>=(lo)) ? (first) : (lo)+(((p)-((lo)%(p)))%(p)) )
239             /* As above, but as an offset from lo, so returns 0+ */
240             #define P_GT_LO_0(first,p,lo) ( ((first)>=(lo)) ? ((first)-(lo)) : (((p)-((lo)%(p)))%(p)) )
241              
242             #endif