moon_math/
lib.rs

1use getrandom::getrandom;
2
3pub fn rand_usize(index: usize) -> usize {
4	let mut new_index = index.to_ne_bytes();
5	let err = getrandom(&mut new_index);
6	match err {
7		Err(err) => println!("Problem generating random usize: {}", err),
8		Ok(()) => ()
9	};
10	usize::from_ne_bytes(new_index)
11}
12
13pub fn shuffle_vec (v: &mut Vec<u32>) {
14	//For each index, grab a random value stored between that index and the final index
15	//(inclusive of current and final indices) then swap that with the current index.
16	//If the current index is chosen, it remains the same. (Swaps with itself).
17	//Don't add an if statement to check is i == k, it just add cycles in most cases.
18	for i in 0..v.len() - 1 {
19		let k = i + (rand_usize(i) % (v.len() - i));
20		let temp = v[i];
21		v[i] = v[k];
22		v[k] = temp;
23	}
24}
25
26pub fn test_prime(sieve: &Vec<u32>, test_prime: &u32) -> bool {
27	//A heuristic sqrt(n) search to then logarithmically find how much of the sieve is larger than the sqrt could be good.
28	//This does not protect against sieve[-1] being greater than test_prime
29	for i in 1..sieve.len() {
30		match test_prime % sieve[i] { 
31			0 => return false, 
32			_ => continue
33		}
34	}
35	true
36}
37
38pub fn prime_sieve(n: u32) -> Vec<u32> {
39	if n < 2 { return vec!(); }
40	
41	let mut sieve = vec!(2);
42	let mut test_val = 3;
43	
44	while test_val <= n {
45		if test_prime(&sieve, &test_val) { 
46			sieve.push(test_val); 
47		}
48		test_val += 2; 
49	}
50	
51	sieve
52}
53
54pub fn factorial(n: u32) -> u128 {
55	if n == 0 || n == 1 { return 1; }
56	if n == 2 { return 2; }
57	if n < 2 {
58		let mut fac: u32 = 2;
59		for f in 3..n+1 { fac *= f; }
60		return u128::from(fac);
61	}
62	
63	let mut fac: u128 = 1;
64	let sieve = prime_sieve(n);
65	let mut moving_n = n;
66	println!("");
67	let mut power = 1;
68	loop {
69		let mut swing_fac:u128 = 1;
70		
71		for p in sieve.iter() {
72			if p > &moving_n { break; }
73			let mut q = moving_n;
74			let mut f = 1;
75			
76			while q > 1 {
77				q /= p;
78				if q & 1 > 0 { f *= p; }
79			}
80			
81			swing_fac *= u128::from(f);
82		}
83		
84		fac *= swing_fac.pow(power);
85		power = power << 1;
86		
87		moving_n = moving_n >> 1;
88		if moving_n <= 1 { return u128::from(fac); }
89	}
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96	#[test]
97	fn test_random() {
98		for i in 0..10 {
99			println!("{}", rand_usize(i));
100		}
101	}
102
103	#[test]
104	fn test_prime_sieve() {
105		assert_eq!(prime_sieve(2), vec!(2));
106		assert_eq!(prime_sieve(3), vec!(2, 3));
107		assert_eq!(prime_sieve(4), vec!(2, 3));
108		assert_eq!(prime_sieve(6), vec!(2, 3, 5));
109		assert_eq!(prime_sieve(15), vec!(2, 3, 5, 7, 11, 13));
110	}
111	
112	#[test]
113	fn test_factorial() {
114		let facs = vec!(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600);
115		for i in 0..facs.len() {
116			assert_eq!(factorial(u32::try_from(i).unwrap()), facs[i]);
117		}
118	}
119}