1use super::general::*;
9use crate::math::constants;
10pub trait Primality {
12 #[must_use]
89 fn is_prime(&self) -> bool;
90}
91
92impl Primality for u8 {
93 #[inline]
94 fn is_prime(&self) -> bool {
95 if self < &2
96 { return false; }
97
98 for i in constants::PRIMELIST[..6].iter() {
99 if *self == *i as u8
100 { return true; }
101 if self % *i as u8 == 0
102 { return false; }
103 }
104 true
105 }
106}
107
108impl Primality for u16 {fn is_prime(&self) -> bool {
110 if *self <= u8::MAX as u16
111 { return (*self as u8).is_prime(); }
112
113 constants::PRIMELIST.binary_search(self).is_ok()
114 }
115}
116
117impl Primality for u32 {
118 fn is_prime(&self) -> bool {
119 if *self <= u16::MAX as u32
120 { return (*self as u16).is_prime(); }
121
122 for i in constants::PRIMELIST[..30].iter() {
123 if self % *i as u32 == 0
124 { return false; }
125 }
126 machine_word_prime_32(*self)
127 }
128}
129
130impl Primality for i32 {
131 fn is_prime(&self) -> bool {
132 if self <= &0 { return false; }
133 (*self as u32).is_prime()
134 }
135}
136
137impl Primality for u64 {
138 fn is_prime(&self) -> bool {
139 if *self <= u32::MAX as u64
140 { return (*self as u32).is_prime(); }
141
142 for i in constants::PRIMELIST[..30].iter() {
143 if self % *i as u64 == 0
144 { return false; }
145 }
146
147 machine_word_prime_64(*self)
148 }
149}
150
151impl Primality for i64 {
152 fn is_prime(&self) -> bool {
153 if self <= &0 { return false; }
154 (*self as u64).is_prime()
155 }
156}
157
158impl Primality for u128 {
159 fn is_prime(&self) -> bool {
160 if *self <= u64::MAX as u128
161 { return (*self as u64).is_prime(); }
162 unimplemented!("is_prime is currently not implemented for u128/i128 values bigger than 2^64 - 1.")
163 }
164}
165
166impl Primality for i128 {
167 fn is_prime(&self) -> bool {
168 if self <= &0 { return false; }
169 (*self as u128).is_prime()
170 }
171}
172
173#[must_use]
186pub fn generate_primes(limit: usize) -> Vec<usize> {
187 match limit {
188 0 | 1 => { return Vec::new(); }
189 2 => { return vec![2]; }
190 3 => { return vec![2, 3]; }
191 _ => { }
192 }
193
194 let mut res: Vec<usize> = Vec::with_capacity(limit >> 2 + 2);
195 res.push(2);
196 res.push(3);
197 let mut n: usize;
198 let mut sieve: Vec<bool> = vec![false; limit];
199
200 for x in (1..).take_while(|n| n.square() < limit) {
201 for y in (1..).take_while(|n| n.square() < limit) {
202
203 n = 4 * x.square() + y.square();
204 if n <= limit && (n % 12 == 1 || n % 12 == 5)
205 { sieve[n] ^= true; }
206
207 n = 3 * x.square() + y.square();
208 if n <= limit && n % 12 == 7
209 { sieve[n] ^= true; }
210
211 if x > y {
212 n = 3 * x.square() - y.square();
213 if n <= limit && n % 12 == 11
214 { sieve[n] ^= true; }
215 }
216 }
217 }
218
219 for r in (5..).take_while(|n| n.square() < limit) {
220 if sieve[r] {
221 for i in (r.square()..limit).step_by(r.square()) {
222 sieve[i] = false;
223 }
224 }
225 }
226
227 for (i, val) in sieve.iter().enumerate() {
228 if *val { res.push(i); }
229 }
230 res
231}
232#[must_use]
233fn machine_word_prime_32(n: u32) -> bool {
234 let mut x: u64 = (((n >> 16) ^ n) as u128 * 0x45d9f3b) as u64;
235 x = (((x >> 16) ^ x) as u128 * 0x45d9f3b) as u64;
236 x = ((x >> 16) ^ x) & 255;
237
238 sprp_32(n, constants::BASES_32[x as usize] as u32)
239}
240#[must_use]
241fn machine_word_prime_64(x: u64) -> bool {
242
243 if !sprp_64(x, 2)
244 { return false; }
245
246 let mut h = x;
247 h = (((h >> 32) ^ h) as u128 * 0x45d9f3b3335b369) as u64;
248 h = (((h >> 32) ^ h) as u128 * 0x3335b36945d9f3b) as u64;
249 h = (h >> 32) ^ h;
250
251 let b: u32 = constants::BASES_64[(h & 16383) as usize];
252 sprp_64(x, (b & 4095) as u64) && sprp_64(x, (b >> 12) as u64)
253}
254#[must_use]
255fn sprp_32(p: u32, base: u32) -> bool { let zeroes: u32 = (p - 1).trailing_zeros(); let d: u32 = (p - 1) >> zeroes;
258 let mut x: u32 = mod_pow_32(&base, &d, &p); if x == 1 || x == p - 1 { return true; }
262
263 for _ in 0..zeroes - 1 { x = ((x as u64).square() % p as u64) as u32;
265 if x == p - 1
266 { return true; }
267 }
268 false
269}
270#[must_use]
271fn sprp_64(p: u64, base: u64) -> bool {
272 let zeroes: u32 = (p - 1).trailing_zeros();
273 let d: u64 = (p - 1) >> zeroes;
274 let mut x: u64 = mod_pow_64(&base, &d, &p);
275
276 if x == 1 || x == p - 1
277 { return true; }
278
279 for _ in 0..zeroes - 1 {
280 x = (((x as u128).square()) % p as u128) as u64;
281 if x == p - 1
282 { return true; }
283 }
284 false
285}
286#[must_use]
287const fn mod_pow_64(c: &u64, p: &u64, modulus: &u64) -> u64 {
288 if *modulus == 0
289 { return *modulus; }
290 if *p == 0
291 { return 1; }
292 let mut z: u128 = 1;
293 let mut base: u128 = *c as u128;
294 let n: u128 = *modulus as u128;
295 let mut pow: u64 = *p;
296
297 while pow > 1 {
298
299 if pow & 1 == 0 {
300 base = base * base % n;
301 pow >>= 1;
302 continue;
303 }
304 z = base * z % n;
305 base = base * base % n;
306 pow = (pow - 1) >> 1;
307 }
308 (base * z % n) as u64
309}
310#[must_use]
311const fn mod_pow_32(c: &u32, p: &u32, modulus: &u32) -> u32 {
312 if *modulus == 0
313 { return 0; }
314 if *p == 0
315 { return 1; }
316 let mut z: u64 = 1;
317 let mut base: u64 = *c as u64;
318 let n: u64 = *modulus as u64;
319 let mut pow: u32 = *p;
320
321 while pow > 1 {
322
323 if pow & 1 == 0 {
324 base = base * base % n;
325 pow >>= 1;
326 continue;
327 }
328 z = base * z % n;
329 base = base * base % n;
330 pow = (pow - 1) >> 1;
331 }
332 (base * z % n) as u32
333}