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
use crate::unsigned_integer::traits::IsUnsignedInteger;

pub trait IsGroup: Clone + PartialEq + Eq {
    /// Returns the neutral element of the group. The equality
    /// `neutral_element().operate_with(g) == g` must hold
    /// for every group element `g`.
    fn neutral_element() -> Self;

    /// Check if an element the neutral element.
    fn is_neutral_element(&self) -> bool {
        self == &Self::neutral_element()
    }

    /// Applies the group operation `times` times with itself
    /// The operation can be addition or multiplication depending on
    /// the notation of the particular group.
    fn operate_with_self<T: IsUnsignedInteger>(&self, mut exponent: T) -> Self {
        let mut result = Self::neutral_element();
        let mut base = self.clone();

        while exponent != T::from(0) {
            if exponent & T::from(1) == T::from(1) {
                result = Self::operate_with(&result, &base);
            }
            exponent >>= 1;
            base = Self::operate_with(&base, &base);
        }
        result
    }

    /// Applies the group operation between `self` and `other`.
    /// The operation can be addition or multiplication depending on
    /// the notation of the particular group.
    fn operate_with(&self, other: &Self) -> Self;

    fn neg(&self) -> Self;
}