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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
/// Adds `calc_remainders(divisor)` method to types that have some implementation of the Division trait.
pub(super) trait CalcRemainders<T, D>{
fn calc_remainders(self, divisor : D) -> Remainders<T,D>;
}
/// Implement `Division` to enable the `calc_remainders()` method for your type.
pub(super) trait Division<D> where Self:Sized {
/// does in-place arbitrary-length division. Returns remainder.
fn divide(self, divisor : &D) -> DivisionResult<Self, D>;
fn is_zero(&self) -> bool;
}
/// Or mark your type as `UseGenericDivision` to just use `/` and `%` operators for types. Makes only sense for integers.
pub(super) trait UseGenericDivision : Clone
+ for <'a> std::ops::Div<&'a Self, Output = Self>
+ for <'a> std::ops::Rem<&'a Self, Output = Self>
+ Default
+ Eq {}
impl<T, D> CalcRemainders<T, D> for T
where T:Division<D>
{
fn calc_remainders(self, divisor : D) -> Remainders<T, D> {
Remainders::new(self,divisor)
}
}
pub(super) struct Remainders<T, U>{
value : Option<T>,
divisor : U,
}
impl<U, T:Division<U>> Remainders<T, U> {
fn new(value : T, divisor : U) -> Self {
let value = if value.is_zero() { None } else { Some(value) };
Remainders {
value,
divisor,
}
}
}
impl<U, T:Division<U>> Iterator for Remainders<T,U>{
type Item=U;
fn next(&mut self) -> Option<Self::Item> {
if let Some(v) = self.value.take() {
let DivisionResult{result, remainder} = v.divide(&self.divisor);
self.value = if result.is_zero() { None } else { Some(result) };
Some(remainder)
} else {
None
}
}
}
pub(super) struct DivisionResult<T:Division<U>, U> {
pub result : T,
pub remainder : U,
}
impl<U> Division<U> for U
where U: UseGenericDivision
{
fn divide(self, divisor : &Self) -> DivisionResult<Self, Self> {
DivisionResult {
result: self.clone().div(divisor),
remainder: self.rem(divisor)
}
}
fn is_zero(&self) -> bool {
*self == Self::default()
}
}
|