Skip to content

Instantly share code, notes, and snippets.

@mverleg
Last active July 31, 2018 19:56
Show Gist options
  • Save mverleg/c14d7fa93e3613fe8345e388222b193b to your computer and use it in GitHub Desktop.
Save mverleg/c14d7fa93e3613fe8345e388222b193b to your computer and use it in GitHub Desktop.
Implement modulo operation for types that have remainder implemented (and add and clone), with specialization for copy types
/// Define a modulo operation, in the mathematical sense.
/// This differs from Rem because the result is always non-negative.
pub trait Modulo<T> {
type Output;
#[inline]
fn modulo(self, other: T) -> Self::Output;
}
/// Implement modulo operation for types that implement Rem, Add and Clone.
// Add and Clone are needed to shift the value by U if it is below zero.
// TODO @mverleg: describe constraint on output type
impl<U, T> Modulo<T> for U
where
T: Clone,
U: Rem<T>,
<U as Rem<T>>::Output: Add<T>,
<<U as Rem<T>>::Output as Add<T>>::Output: Rem<T>
{
type Output = <<<U as Rem<T>>::Output as Add<T>>::Output as Rem<T>>::Output;
#[inline]
default fn modulo(self, other: T) -> Self::Output {
((self % other.clone()) + other.clone()) % other
}
}
/// Implement a potentially faster modulo operation for types that are Copy-able.
impl<U, T> Modulo<T> for U
where
T: Clone + Copy,
U: Rem<T>,
<U as Rem<T>>::Output: Add<T>,
<<U as Rem<T>>::Output as Add<T>>::Output: Rem<T>
{
#[inline]
fn modulo(self, other: T) -> Self::Output {
((self % other) + other) % other
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment