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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use std::marker::PhantomData;
use Construct;
use Count;
use ToIndex;
use ToPos;
use Zero;
pub struct Either<T, U>(PhantomData<T>, PhantomData<U>);
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Select<T, U> {
Fst(T),
Snd(U),
}
impl<T, U> Construct for Either<T, U>
where T: Construct,
U: Construct
{
fn new() -> Either<T, U> {
Either(PhantomData, PhantomData)
}
}
impl<T, U, V, W> Count<(V, W)> for Either<T, U>
where T: Construct + Count<V>,
U: Construct + Count<W>
{
fn count(&self, &(ref dim_t, ref dim_u): &(V, W)) -> usize {
let t: T = Construct::new();
let u: U = Construct::new();
t.count(dim_t) + u.count(dim_u)
}
}
impl<T, U, V, W, X, Y> Zero<(V, W), Select<X, Y>> for Either<T, U>
where T: Construct + Zero<V, X>
{
fn zero(&self, &(ref dim_t, _): &(V, W)) -> Select<X, Y> {
let t: T = Construct::new();
Select::Fst(t.zero(dim_t))
}
}
impl<T, U, V, W, X, Y> ToIndex<(V, W), Select<X, Y>> for Either<T, U>
where T: Construct + Count<V> + ToIndex<V, X>,
U: Construct + ToIndex<W, Y>
{
fn to_index(
&self,
&(ref dim_t, ref dim_u): &(V, W),
s: &Select<X, Y>
) -> usize {
let t: T = Construct::new();
let u: U = Construct::new();
match *s {
Select::Fst(ref pt) => {
t.to_index(dim_t, pt)
}
Select::Snd(ref pu) => {
let count = t.count(dim_t);
count + u.to_index(dim_u, pu)
}
}
}
}
impl<T, U, V, W, X, Y> ToPos<(V, W), Select<X, Y>> for Either<T, U>
where T: Construct + Count<V> + ToPos<V, X> + Zero<V, X>,
U: Construct + ToPos<W, Y> + Zero<W, Y>
{
fn to_pos(
&self,
&(ref dim_t, ref dim_u): &(V, W),
ind: usize,
pos: &mut Select<X, Y>
) {
let t: T = Construct::new();
let u: U = Construct::new();
let count = t.count(dim_t);
if ind < count {
let mut zero = t.zero(dim_t);
t.to_pos(dim_t, ind, &mut zero);
*pos = Select::Fst(zero)
} else {
let mut zero = u.zero(dim_u);
u.to_pos(dim_u, ind - count, &mut zero);
*pos = Select::Snd(zero)
}
}
}