modulo/
lib.rs

1use std::ops::{Rem, Add};
2/// Trait that describes modulo operation
3/// # Examples
4///
5/// ```ยจ
6/// use modulo::Mod;
7/// fn main() {
8///     assert_eq!(4, (-2).modulo(6));
9///     assert_eq!(2, 9.modulo(7));
10/// }
11/// ```
12pub trait Mod<RHS=Self> {
13    type Output;
14    #[inline]
15    fn modulo(self, rhs: RHS) -> Self::Output;
16}
17
18impl<A, B, C> Mod<B> for A where A: Rem<B, Output=C>, B: Clone, C: Add<B, Output=C> + Default + PartialOrd {
19    type Output = C;
20    fn modulo(self, rhs: B) -> Self::Output {
21        let result = self % rhs.clone();
22        if result < Self::Output::default() {
23            result + rhs
24        } else {
25            result
26        }
27    }
28}
29
30#[cfg(test)]
31mod test {
32    use super::Mod;
33
34    #[test]
35    fn smaller_than_modulus_works() {
36        assert_eq!(3, 3.modulo(9));
37        assert_eq!(7, 7.modulo(8));
38    }
39
40    #[test]
41    fn larger_than_modulus_works() {
42        assert_eq!(1, 6.modulo(5));
43        assert_eq!(8, 18.modulo(10));
44    }
45
46    #[test]
47    fn megative_works() {
48        assert_eq!(1, (-1).modulo(2));
49        assert_eq!(2, (-7).modulo(3));
50    }
51
52    #[test]
53    fn big_number_works() {
54        assert_eq!(1, 101.modulo(10));
55    }
56}