1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//! Euler の $\\varphi$ 関数。

use super::factors;

use factors::Factors;

/// Euler の $\\varphi$ 関数。
///
/// $n$ 以下の自然数のうち、$n$ と互いに素であるものの個数を返す。$1$
/// と $1$ は互いに素であることに注意。
///
/// # Note
/// 素数冪 $p^k$, $p\'^{k\'}$ ($p\\ne p\'$) について
/// $\\varphi(p^k p\'^{k\'}) = \\varphi(p^k)\\varphi(p\'^{k\'})$
/// が成り立つ。また、$\\varphi(p^k) = \\varphi^{k-1}\\cdot(p-1)$ が成り立つ。
///
/// # Complexity
/// $O(\\sqrt{n})$ time.
///
/// # Examples
/// ```
/// use nekolib::math::EulerPhi;
///
/// assert_eq!(1_u64.euler_phi(), 1);
/// assert_eq!(60_u64.euler_phi(), 16);
/// ```
pub trait EulerPhi {
    fn euler_phi(self) -> Self;
}

macro_rules! impl_uint {
    ($t:ty) => {
        impl EulerPhi for $t {
            fn euler_phi(self) -> Self {
                self.factors().map(|(p, e)| p.pow(e - 1) * (p - 1)).product()
            }
        }
    };
    ( $($t:ty)* ) => { $(impl_uint!($t);)* };
}

impl_uint!(u8 u16 u32 u64 u128 usize);

#[test]
fn test_naive() {
    use gcd::Gcd;
    let n = 100_usize;
    for i in 1..=n {
        let phi = (1..=i).filter(|&j| i.gcd(j) == 1).count();
        assert_eq!(i.euler_phi(), phi);
    }
}