diff --git a/src/lib.rs b/src/lib.rs index 8e6daf9..4b9da92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -451,3 +451,22 @@ pub fn is_prime(n: u64) -> bool { } firstfac(n) == n } + +/// Euler's totient function, the number of primes between 1 and n inclusive that are relatively +/// prime to n. +pub fn totient(n: u64) -> u64 { + if n <= 0 { + return 0; + } + let mut r = 1u64; + let mut prev = 1u64; + for i in factors(n) { + if i == prev { + r *= i; + } else { + r *= i - 1; + } + prev = i; + } + r +} \ No newline at end of file diff --git a/tests/basictests.rs b/tests/basictests.rs index 70939ff..5644231 100644 --- a/tests/basictests.rs +++ b/tests/basictests.rs @@ -1,4 +1,4 @@ -use primes::{factors, factors_uniq, is_prime, PrimeSet, PrimeSetBasics, Sieve, TrialDivision}; +use primes::{factors, factors_uniq, is_prime, totient, PrimeSet, PrimeSetBasics, Sieve, TrialDivision}; #[test] fn test_primesetbasics() { @@ -145,3 +145,14 @@ fn test_sieve() { assert_eq!(sieved, trialled); } + +#[test] +fn test_totient() { + assert_eq!(totient(1), 1); + assert_eq!(totient(12), 4); + assert_eq!(totient(17), 16); + assert_eq!(totient(120), 32); + assert_eq!(totient(248), 120); + assert_eq!(totient(100000000), 40000000); + assert_eq!(totient(10493938559900), 4197575423920); +} \ No newline at end of file