Skip to content

Commit 4922846

Browse files
authored
Add faster_perfect_numbers and mersenne_primes (#355)
1 parent 8ebcc27 commit 4922846

File tree

3 files changed

+83
-0
lines changed

3 files changed

+83
-0
lines changed

src/math/faster_perfect_numbers.rs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use super::{mersenne_primes::is_mersenne_prime, prime_numbers::prime_numbers};
2+
use std::convert::TryInto;
3+
4+
/*
5+
Generates a list of perfect numbers till `num` using the Lucas Lehmer test algorithm.
6+
url : https://en.wikipedia.org/wiki/Lucas%E2%80%93Lehmer_primality_test
7+
*/
8+
pub fn generate_perfect_numbers(num: usize) -> Vec<usize> {
9+
let mut results = Vec::new();
10+
let prime_limit = get_prime_limit(num);
11+
12+
for i in prime_numbers(prime_limit).iter() {
13+
let prime = *i;
14+
if is_mersenne_prime(prime) {
15+
results.push(
16+
(2_usize.pow(prime.try_into().unwrap()) - 1)
17+
* (2_usize.pow((prime - 1).try_into().unwrap())),
18+
);
19+
}
20+
}
21+
results.into_iter().filter(|x| *x <= num).collect()
22+
}
23+
24+
// Gets an approximate limit for the generate_perfect_numbers function
25+
fn get_prime_limit(num: usize) -> usize {
26+
(((num * 8 + 1) as f64).log2() as usize) / 2_usize
27+
}
28+
29+
#[cfg(test)]
30+
mod tests {
31+
use super::*;
32+
33+
#[test]
34+
fn perfect_numbers_till_n() {
35+
let n = 335564540;
36+
assert_eq!(generate_perfect_numbers(n), [6, 28, 496, 8128, 33550336]);
37+
assert_eq!(generate_perfect_numbers(40), [6, 28]);
38+
assert_eq!(generate_perfect_numbers(0), []);
39+
}
40+
}

src/math/mersenne_primes.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// mersenne prime : https://en.wikipedia.org/wiki/Mersenne_prime
2+
pub fn is_mersenne_prime(n: usize) -> bool {
3+
if n == 2 {
4+
return true;
5+
}
6+
let mut s = 4;
7+
let m = 2_usize.pow(std::convert::TryInto::try_into(n).unwrap()) - 1;
8+
for _ in 0..n - 2 {
9+
s = ((s * s) - 2) % m;
10+
}
11+
s == 0
12+
}
13+
14+
pub fn get_mersenne_primes(limit: usize) -> Vec<usize> {
15+
let mut results: Vec<usize> = Vec::new();
16+
for num in 1..=limit {
17+
if is_mersenne_prime(num) {
18+
results.push(num);
19+
}
20+
}
21+
results
22+
}
23+
24+
#[cfg(test)]
25+
mod tests {
26+
use super::{get_mersenne_primes, is_mersenne_prime};
27+
28+
#[test]
29+
fn validity_check() {
30+
assert!(is_mersenne_prime(3));
31+
assert!(is_mersenne_prime(13));
32+
assert!(!is_mersenne_prime(32));
33+
}
34+
35+
#[allow(dead_code)]
36+
fn generation_check() {
37+
assert_eq!(get_mersenne_primes(30), [2, 3, 5, 7, 13, 17, 19]);
38+
}
39+
}

src/math/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ mod baby_step_giant_step;
33
mod extended_euclidean_algorithm;
44
mod fast_fourier_transform;
55
mod fast_power;
6+
mod faster_perfect_numbers;
67
mod gaussian_elimination;
78
mod gcd_of_n_numbers;
89
mod greatest_common_divisor;
910
mod karatsuba_multiplication;
1011
mod lcm_of_n_numbers;
1112
mod linear_sieve;
1213
mod matrix_ops;
14+
mod mersenne_primes;
1315
mod miller_rabin;
1416
mod newton_raphson;
1517
mod nthprime;
@@ -35,6 +37,7 @@ pub use self::fast_fourier_transform::{
3537
inverse_fast_fourier_transform,
3638
};
3739
pub use self::fast_power::fast_power;
40+
pub use self::faster_perfect_numbers::generate_perfect_numbers;
3841
pub use self::gaussian_elimination::gaussian_elimination;
3942
pub use self::gcd_of_n_numbers::gcd;
4043
pub use self::greatest_common_divisor::{
@@ -46,6 +49,7 @@ pub use self::linear_sieve::LinearSieve;
4649
pub use self::matrix_ops::{
4750
matrix_add, matrix_multiply, matrix_scalar_multiplication, matrix_subtract, matrix_transpose,
4851
};
52+
pub use self::mersenne_primes::{get_mersenne_primes, is_mersenne_prime};
4953
pub use self::miller_rabin::miller_rabin;
5054
pub use self::newton_raphson::find_root;
5155
pub use self::nthprime::nthprime;

0 commit comments

Comments
 (0)