discrete/
either.rs

1use std::marker::PhantomData;
2
3use std::ops::{Add, Sub};
4
5use Construct;
6use space::Space;
7
8/// Selects between two spaces.
9pub struct Either<T, U>(PhantomData<T>, PhantomData<U>);
10
11/// Selects between spaces.
12#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
13pub enum Select<T, U> {
14    /// The first space.
15    Fst(T),
16    /// The second space.
17    Snd(U),
18}
19
20impl<T, U> Construct for Either<T, U> {
21    fn new() -> Self { Either(PhantomData, PhantomData) }
22}
23
24impl<T, U, N> Space<N> for Either<T, U>
25    where T: Space<N>,
26          U: Space<N>,
27          N: Add<Output = N> +
28             Sub<Output = N> +
29             PartialOrd,
30{
31    type Dim = (T::Dim, U::Dim);
32    type Pos = Select<T::Pos, U::Pos>;
33    fn count(&self, &(ref dim_t, ref dim_u): &Self::Dim) -> N {
34        let t: T = Construct::new();
35        let u: U = Construct::new();
36        t.count(dim_t) + u.count(dim_u)
37    }
38    fn zero(&self, &(ref dim_t, _): &Self::Dim) -> Self::Pos {
39        let t: T = Construct::new();
40        Select::Fst(t.zero(dim_t))
41    }
42    fn to_index(
43        &self,
44        &(ref dim_t, ref dim_u): &Self::Dim,
45        s: &Self::Pos
46    ) -> N {
47        let t: T = Construct::new();
48        let u: U = Construct::new();
49        match *s {
50            Select::Fst(ref pt) => {
51                t.to_index(dim_t, pt)
52            }
53            Select::Snd(ref pu) => {
54                let count = t.count(dim_t);
55                count + u.to_index(dim_u, pu)
56            }
57        }
58    }
59    fn to_pos(
60        &self,
61        &(ref dim_t, ref dim_u): &Self::Dim,
62        ind: N,
63        pos: &mut Self::Pos,
64    ) {
65        let t: T = Construct::new();
66        let u: U = Construct::new();
67        let count = t.count(dim_t);
68        if ind < count {
69            let mut zero = t.zero(dim_t);
70            t.to_pos(dim_t, ind, &mut zero);
71            *pos = Select::Fst(zero)
72        } else {
73            let mut zero = u.zero(dim_u);
74            u.to_pos(dim_u, ind - count, &mut zero);
75            *pos = Select::Snd(zero)
76        }
77    }
78}