<commit_before>pub type BoxedScene<EventT, RendererT, EngineDataT> = Box<Scene<EventT, RendererT, EngineDataT> + 'static>;
pub type SceneChangeCallback<EventT, RendererT, EngineDataT> = Box<Fn() -> BoxedScene<EventT, RendererT, EngineDataT>>;

pub trait Scene<EventT, RendererT, EngineDataT> {
    fn render(&self, renderer: &mut RendererT, engine_data: &mut EngineDataT, tick: u64);
    fn handle_event(&mut self, event: &EventT, renderer: &mut RendererT, engine_data: &mut EngineDataT, tick: u64) -> Option<SceneChangeEvent<EventT, RendererT, EngineDataT>>;
}

pub enum SceneChangeEvent<EventT, RendererT, EngineDataT> {
    PushScene(SceneChangeCallback<EventT, RendererT, EngineDataT>),
    SwapScene(SceneChangeCallback<EventT, RendererT, EngineDataT>),
    PopScene,
}

pub struct SceneStack<EventT, RendererT, EngineDataT> {
    scenes: Vec<BoxedScene<EventT, RendererT, EngineDataT>>
}

impl<EventT, RendererT, EngineDataT> SceneStack<EventT, RendererT, EngineDataT> {

    pub fn new() -> SceneStack<EngineDataT, EventT, RendererT> {
        SceneStack {
            scenes: vec![]
        }
    }

    pub fn is_empty(&self) -> bool {
        self.scenes.len() == 0
    }

    pub fn push(&mut self, scene: BoxedScene<EventT, RendererT, EngineDataT>) {
        self.scenes.push(scene)
    }

    pub fn swap(&mut self, scene: BoxedScene<EventT, RendererT, EngineDataT>) -> Option<BoxedScene<EventT, RendererT, EngineDataT>> {
        let old_scene = self.scenes.pop();
        self.scenes.push(scene);
        old_scene
    }

    pub fn pop(&mut self) -> Option<BoxedScene<EventT, RendererT, EngineDataT>> {
        self.scenes.pop()
    }

    pub fn render(&mut self, renderer: &mut RendererT, engine_data: &mut EngineDataT, tick: u64) {
        let maybe_last_scene = self.scenes.pop();
        match maybe_last_scene {
            Some(scene) => {
                scene.render(renderer, engine_data, tick);
                self.scenes.push(scene);
            },
            None => ()
        }
    }

    pub fn handle_event(&mut self, event: &EventT, renderer: &mut RendererT, engine_data: &mut EngineDataT, tick: u64) {
        let maybe_last_scene = self.scenes.pop();
        let event = match maybe_last_scene {
            Some(mut scene) => {
                let event = scene.handle_event(event, renderer, engine_data, tick);
                self.scenes.push(scene);
                event
            },
            None => None
        };

        match event {
            Some(SceneChangeEvent::PushScene(callback)) => {
                self.push(callback());
            },
            Some(SceneChangeEvent::SwapScene(callback)) => {
                self.swap(callback());
            },
            Some(SceneChangeEvent::PopScene) => {
                self.pop();
            },
            None => ()
        };
    }
}
<commit_msg>Pass world state information into callback generators<commit_after>pub type BoxedScene<EventT, RendererT, EngineDataT> = Box<Scene<EventT, RendererT, EngineDataT> + 'static>;
pub type SceneChangeCallback<EventT, RendererT, EngineDataT> = Box<Fn(&mut RendererT, &mut EngineDataT) -> BoxedScene<EventT, RendererT, EngineDataT>>;

pub trait Scene<EventT, RendererT, EngineDataT> {
    fn render(&self, renderer: &mut RendererT, engine_data: &mut EngineDataT, tick: u64);
    fn handle_event(&mut self, event: &EventT, renderer: &mut RendererT, engine_data: &mut EngineDataT, tick: u64) -> Option<SceneChangeEvent<EventT, RendererT, EngineDataT>>;
}

pub enum SceneChangeEvent<EventT, RendererT, EngineDataT> {
    PushScene(SceneChangeCallback<EventT, RendererT, EngineDataT>),
    SwapScene(SceneChangeCallback<EventT, RendererT, EngineDataT>),
    PopScene,
}

pub struct SceneStack<EventT, RendererT, EngineDataT> {
    scenes: Vec<BoxedScene<EventT, RendererT, EngineDataT>>
}

impl<EventT, RendererT, EngineDataT> SceneStack<EventT, RendererT, EngineDataT> {

    pub fn new() -> SceneStack<EngineDataT, EventT, RendererT> {
        SceneStack {
            scenes: vec![]
        }
    }

    pub fn is_empty(&self) -> bool {
        self.scenes.len() == 0
    }

    pub fn push(&mut self, scene: BoxedScene<EventT, RendererT, EngineDataT>) {
        self.scenes.push(scene)
    }

    pub fn swap(&mut self, scene: BoxedScene<EventT, RendererT, EngineDataT>) -> Option<BoxedScene<EventT, RendererT, EngineDataT>> {
        let old_scene = self.scenes.pop();
        self.scenes.push(scene);
        old_scene
    }

    pub fn pop(&mut self) -> Option<BoxedScene<EventT, RendererT, EngineDataT>> {
        self.scenes.pop()
    }

    pub fn render(&mut self, renderer: &mut RendererT, engine_data: &mut EngineDataT, tick: u64) {
        let maybe_last_scene = self.scenes.pop();
        match maybe_last_scene {
            Some(scene) => {
                scene.render(renderer, engine_data, tick);
                self.scenes.push(scene);
            },
            None => ()
        }
    }

    pub fn handle_event(&mut self, event: &EventT, renderer: &mut RendererT, engine_data: &mut EngineDataT, tick: u64) {
        let maybe_last_scene = self.scenes.pop();
        let event = match maybe_last_scene {
            Some(mut scene) => {
                let event = scene.handle_event(event, renderer, engine_data, tick);
                self.scenes.push(scene);
                event
            },
            None => None
        };

        match event {
            Some(SceneChangeEvent::PushScene(callback)) => {
                self.push(callback(renderer, engine_data));
            },
            Some(SceneChangeEvent::SwapScene(callback)) => {
                self.swap(callback(renderer, engine_data));
            },
            Some(SceneChangeEvent::PopScene) => {
                self.pop();
            },
            None => ()
        };
    }
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Google Inc. All rights reserved.
Copyright 2017 Jihyun Yu. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

use std;

use consts::EPSILON;

/// Interval represents a closed interval on ℝ.
/// Zero-length intervals (where Lo == Hi) represent single points.
/// If Lo > Hi then the interval is empty.
#[derive(Clone,Copy,Default)]
pub struct Interval {
    /// lower bound of the interval
    pub lo: f64,
    /// upper bound of the interval
    pub hi: f64,
}
impl std::fmt::Debug for Interval {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "[{:.7}, {:.7}]", self.lo, self.hi)
    }
}

pub const EMPTY: Interval = Interval { lo: 1., hi: 0. };

impl Interval {
    /// empty returns an empty interval.
    pub fn empty() -> Self {
        EMPTY
    }

    /// from_point returns an interval representing a single point.
    pub fn from_point(p: f64) -> Self {
        Interval { lo: p, hi: p }
    }

    /// is_empty reports whether the interval is empty.
    pub fn is_empty(&self) -> bool {
        self.lo > self.hi
    }

    /// center returns the midpoint of the interval.
    /// It is undefined for empty intervals.
    pub fn center(&self) -> f64 {
        0.5f64 * (self.lo + self.hi)
    }

    /// len returns the length of the interval.
    /// The length of an empty interval is negative.
    pub fn len(&self) -> f64 {
        self.hi - self.lo
    }

    /// contains returns true iff the interval contains p.
    pub fn contains(&self, p: f64) -> bool {
        self.lo <= p && p <= self.hi
    }

    /// contains_interval returns true iff the interval contains oi.
    pub fn contains_interval(&self, oi: &Self) -> bool {
        if oi.is_empty() {
            true
        } else {
            self.lo <= oi.lo && oi.hi <= self.hi
        }
    }

    /// interior_contains returns true iff the the interval strictly contains p.
    pub fn interior_contains(&self, p: f64) -> bool {
        self.lo < p && p < self.hi
    }

    /// interior_contains_interval returns true iff the interval strictly contains oi.
    pub fn interior_contains_interval(&self, oi: &Self) -> bool {
        if oi.is_empty() {
            true
        } else {
            self.lo < oi.lo && oi.hi < self.hi
        }
    }

    /// intersects returns true iff the interval contains any points in common with oi.
    pub fn intersects(&self, oi: &Self) -> bool {
        if self.lo <= oi.lo {
            // oi.Lo ∈ i and oi is not empty
            oi.lo <= self.hi && oi.lo <= oi.hi
        } else {
            // i.Lo ∈ oi and i is not empty
            self.lo <= oi.hi && self.lo <= self.hi
        }
    }

    /// interior_intersects returns true iff the interior of the interval contains any points in
    /// common with oi, including the latter's boundary.
    pub fn interior_intersects(&self, oi: &Self) -> bool {
        oi.lo < self.hi && self.lo < oi.hi && self.lo < self.hi && oi.lo <= oi.hi
    }

    /// intersection returns the interval containing all points common to i and j.
    pub fn intersection(&self, other: &Self) -> Self {
        // Empty intervals do not need to be special-cased.
        Interval {
            lo: self.lo.max(other.lo),
            hi: self.hi.min(other.hi),
        }
    }

    /// clamp_point returns the closest point in the interval to the given point "p".
    /// The interval must be non-empty.
    pub fn clamp_point(&self, p: f64) -> f64 {
        self.lo.max(self.hi.min(p))
    }

    /// expanded returns an interval that has been expanded on each side by margin.
    /// If margin is negative, then the function shrinks the interval on
    /// each side by margin instead. The resulting interval may be empty. Any
    /// expansion of an empty interval remains empty.
    pub fn expanded(&self, margin: f64) -> Self {
        if self.is_empty() {
            self.clone()
        } else {
            Interval {
                lo: self.lo - margin,
                hi: self.hi + margin,
            }
        }
    }

    /// union returns the smallest interval that contains this interval and the given interval.
    pub fn union(&self, other: &Self) -> Self {
        if self.is_empty() {
            other.clone()
        } else if other.is_empty() {
            self.clone()
        } else {
            Interval {
                lo: self.lo.min(other.lo),
                hi: self.hi.max(other.hi),
            }
        }
    }

    /// approx_eq reports whether the interval can be transformed into the
    /// given interval by moving each endpoint a small distance.
    /// The empty interval is considered to be positioned arbitrarily on the
    /// real line, so any interval with a small enough length will match
    /// the empty interval.
    pub fn approx_eq(&self, other: &Self) -> bool {
        if self.is_empty() {
            other.len() < 2f64 * EPSILON
        } else if other.is_empty() {
            self.len() < 2f64 * EPSILON
        } else {
            (self.lo - other.lo).abs() <= EPSILON && (self.hi - other.hi).abs() <= EPSILON

        }
    }
}

impl std::ops::Add<f64> for Interval {
    type Output = Interval;
    fn add(self, p: f64) -> Self::Output {
        &self + p
    }
}
impl<'a> std::ops::Add<f64> for &'a Interval {
    type Output = Interval;
    /// returns the interval expanded so that it contains the given point.
    fn add(self, p: f64) -> Self::Output {
        if self.is_empty() {
            Interval { lo: p, hi: p }
        } else if p < self.lo {
            Interval { lo: p, hi: self.hi }
        } else if p > self.hi {
            Interval { lo: self.lo, hi: p }
        } else {
            self.clone()
        }
    }
}

impl std::cmp::PartialEq<Interval> for Interval {
    /// returns true iff the interval contains the same points as other.
    fn eq(&self, other: &Interval) -> bool {
        (self.lo == other.lo && self.hi == other.hi) || (self.is_empty() && other.is_empty())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    macro_rules! I {
        ($lo: expr, $hi: expr) => {
            Interval{lo: $lo, hi: $hi}
        }
    }

    const UNIT: Interval = I!{0., 1.};
    const NEG_UNIT: Interval = I!{-1., 0.};
    const HALF: Interval = I!{0.5, 0.5};
    const ZERO: Interval = I!{0., 0.};

    #[test]
    fn is_empty() {
        assert_eq!(false, UNIT.is_empty());
        assert_eq!(false, HALF.is_empty());
        assert_eq!(true, EMPTY.is_empty());
        assert_eq!(false, ZERO.is_empty());
    }

    #[test]
    fn center() {
        assert_eq!(UNIT.center(), 0.5);
        assert_eq!(NEG_UNIT.center(), -0.5);
        assert_eq!(HALF.center(), 0.5);
    }

    #[test]
    fn length() {
        assert_eq!(UNIT.len(), 1.);
        assert_eq!(NEG_UNIT.len(), 1.);
        assert_eq!(HALF.len(), 0.);
    }

    #[test]
    fn interval_contains() {
        assert_eq!(true, UNIT.contains(0.5));
        assert_eq!(true, UNIT.interior_contains(0.5));

        assert_eq!(true, UNIT.contains(0.));
        assert_eq!(false, UNIT.interior_contains(0.));

        assert_eq!(true, UNIT.contains(1.));
        assert_eq!(false, UNIT.interior_contains(1.));
    }

    fn test_interval_ops(have: &Interval,
                         other: &Interval,
                         contains: bool,
                         interior_contains: bool,
                         intersects: bool,
                         interior_intersects: bool) {
        assert_eq!(contains, have.contains_interval(other));
        assert_eq!(interior_contains, have.interior_contains_interval(other));
        assert_eq!(intersects, have.intersects(other));
        assert_eq!(interior_intersects, have.interior_intersects(other));
    }

    #[test]
    fn interval_operations() {
        test_interval_ops(&EMPTY, &EMPTY, true, true, false, false);
        test_interval_ops(&EMPTY, &UNIT, false, false, false, false);
        test_interval_ops(&UNIT, &HALF, true, true, true, true);
        test_interval_ops(&UNIT, &UNIT, true, false, true, true);
        test_interval_ops(&UNIT, &EMPTY, true, true, false, false);
        test_interval_ops(&UNIT, &NEG_UNIT, false, false, true, false);
    }

    #[test]
    fn intersection() {
        assert_eq!(HALF, UNIT.intersection(&HALF));
        assert_eq!(ZERO, UNIT.intersection(&NEG_UNIT));
        assert_eq!(EMPTY, NEG_UNIT.intersection(&HALF));
        assert_eq!(EMPTY, UNIT.intersection(&EMPTY));
        assert_eq!(EMPTY, EMPTY.intersection(&UNIT));
    }

    fn test_union(x: Interval, y: Interval, want: Interval) {
        assert_eq!(want, x.union(&y));
        assert_eq!(want, y.union(&x));
    }

    #[test]
    fn union() {
        let i_99_100 = Interval { lo: 99., hi: 100. };
        test_union(i_99_100.clone(), EMPTY, i_99_100.clone());
        test_union(I!(5., 3.), I!(0., -2.), EMPTY);
        test_union(UNIT, UNIT, UNIT);
        test_union(UNIT, NEG_UNIT, I!(-1., 1.));
        test_union(HALF, UNIT, UNIT);
    }

    #[test]
    fn add() {
        assert_eq!(I!(5., 5.), EMPTY + 5.);
        assert_eq!(I!(-1., 5.), I!(5., 5.) + -1.);
        assert_eq!(I!(-1., 5.), I!(-1., 5.) + -1.);
        assert_eq!(I!(-1., 6.), I!(-1., 5.) + 6.);
    }

    #[test]
    fn clamp_point() {
        let i = I!(0.1, 0.4);
        assert_eq!(0.3, i.clamp_point(0.3));
        assert_eq!(0.1, i.clamp_point(-7.0));
        assert_eq!(0.4, i.clamp_point(0.6));
    }

    #[test]
    fn expanded() {
        assert_eq!(EMPTY, EMPTY.expanded(0.45));
        assert_eq!(I!(-0.5, 1.5), UNIT.expanded(0.5));
        assert_eq!(I!(0.5, 0.5), UNIT.expanded(-0.5));
        assert_eq!(EMPTY, UNIT.expanded(-0.51));
    }

    fn test_approx_eq(i1: &Interval, i2: &Interval, expected: bool) {
        assert_eq!(expected, i1.approx_eq(&i2));
    }

    #[test]
    fn approx_equal() {
        test_approx_eq(&EMPTY, &EMPTY, true);
        test_approx_eq(&EMPTY, &ZERO, true);
        test_approx_eq(&EMPTY, &I!(1., 1.), true);
        test_approx_eq(&EMPTY, &I!(0., 1.), false);
        test_approx_eq(&EMPTY, &I!(1., 1. + 2. * EPSILON), true);

        test_approx_eq(&I!(1., 1.), &I!(1., 1.), true);
        test_approx_eq(&I!(1., 1.), &I!(1. - EPSILON, 1. - EPSILON), true);
        test_approx_eq(&I!(1., 1.), &I!(1. + EPSILON, 1. + EPSILON), true);
        test_approx_eq(&I!(1., 1.), &I!(1. - 3. * EPSILON, 1.), false);
        test_approx_eq(&I!(1., 1.), &I!(1. - EPSILON, 1. + EPSILON), true);
        test_approx_eq(&ZERO, &I!(1., 1.), false);

        test_approx_eq(&I!(1. - EPSILON, 2. + EPSILON), &I!(1., 2.), false);
        test_approx_eq(&I!(1. + EPSILON, 2. - EPSILON), &I!(1., 2.), true);
        test_approx_eq(&I!(1. - 3. * EPSILON, 2. + EPSILON), &I!(1., 2.), false);
        test_approx_eq(&I!(1. + 3. * EPSILON, 2. - EPSILON), &I!(1., 2.), false);
        test_approx_eq(&I!(1. - EPSILON, 2. + 3. * EPSILON), &I!(1., 2.), false);
        test_approx_eq(&I!(1. + EPSILON, 2. - 3. * EPSILON), &I!(1., 2.), false);
    }
}
<commit_msg>r1: add Interval::new<commit_after>/*
Copyright 2014 Google Inc. All rights reserved.
Copyright 2017 Jihyun Yu. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

use std;

use consts::EPSILON;

/// Interval represents a closed interval on ℝ.
/// Zero-length intervals (where Lo == Hi) represent single points.
/// If Lo > Hi then the interval is empty.
#[derive(Clone,Copy,Default)]
pub struct Interval {
    /// lower bound of the interval
    pub lo: f64,
    /// upper bound of the interval
    pub hi: f64,
}
impl std::fmt::Debug for Interval {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "[{:.7}, {:.7}]", self.lo, self.hi)
    }
}

pub const EMPTY: Interval = Interval { lo: 1., hi: 0. };

impl Interval {
    /// empty returns an empty interval.
    pub fn empty() -> Self {
        EMPTY
    }

    pub fn new(lo: f64, hi: f64) -> Self {
        Self { lo, hi }
    }

    /// from_point returns an interval representing a single point.
    pub fn from_point(p: f64) -> Self {
        Self { lo: p, hi: p }
    }

    /// is_empty reports whether the interval is empty.
    pub fn is_empty(&self) -> bool {
        self.lo > self.hi
    }

    /// center returns the midpoint of the interval.
    /// It is undefined for empty intervals.
    pub fn center(&self) -> f64 {
        0.5f64 * (self.lo + self.hi)
    }

    /// len returns the length of the interval.
    /// The length of an empty interval is negative.
    pub fn len(&self) -> f64 {
        self.hi - self.lo
    }

    /// contains returns true iff the interval contains p.
    pub fn contains(&self, p: f64) -> bool {
        self.lo <= p && p <= self.hi
    }

    /// contains_interval returns true iff the interval contains oi.
    pub fn contains_interval(&self, oi: &Self) -> bool {
        if oi.is_empty() {
            true
        } else {
            self.lo <= oi.lo && oi.hi <= self.hi
        }
    }

    /// interior_contains returns true iff the the interval strictly contains p.
    pub fn interior_contains(&self, p: f64) -> bool {
        self.lo < p && p < self.hi
    }

    /// interior_contains_interval returns true iff the interval strictly contains oi.
    pub fn interior_contains_interval(&self, oi: &Self) -> bool {
        if oi.is_empty() {
            true
        } else {
            self.lo < oi.lo && oi.hi < self.hi
        }
    }

    /// intersects returns true iff the interval contains any points in common with oi.
    pub fn intersects(&self, oi: &Self) -> bool {
        if self.lo <= oi.lo {
            // oi.Lo ∈ i and oi is not empty
            oi.lo <= self.hi && oi.lo <= oi.hi
        } else {
            // i.Lo ∈ oi and i is not empty
            self.lo <= oi.hi && self.lo <= self.hi
        }
    }

    /// interior_intersects returns true iff the interior of the interval contains any points in
    /// common with oi, including the latter's boundary.
    pub fn interior_intersects(&self, oi: &Self) -> bool {
        oi.lo < self.hi && self.lo < oi.hi && self.lo < self.hi && oi.lo <= oi.hi
    }

    /// intersection returns the interval containing all points common to i and j.
    pub fn intersection(&self, other: &Self) -> Self {
        // Empty intervals do not need to be special-cased.
        Interval {
            lo: self.lo.max(other.lo),
            hi: self.hi.min(other.hi),
        }
    }

    /// clamp_point returns the closest point in the interval to the given point "p".
    /// The interval must be non-empty.
    pub fn clamp_point(&self, p: f64) -> f64 {
        self.lo.max(self.hi.min(p))
    }

    /// expanded returns an interval that has been expanded on each side by margin.
    /// If margin is negative, then the function shrinks the interval on
    /// each side by margin instead. The resulting interval may be empty. Any
    /// expansion of an empty interval remains empty.
    pub fn expanded(&self, margin: f64) -> Self {
        if self.is_empty() {
            self.clone()
        } else {
            Interval {
                lo: self.lo - margin,
                hi: self.hi + margin,
            }
        }
    }

    /// union returns the smallest interval that contains this interval and the given interval.
    pub fn union(&self, other: &Self) -> Self {
        if self.is_empty() {
            other.clone()
        } else if other.is_empty() {
            self.clone()
        } else {
            Interval {
                lo: self.lo.min(other.lo),
                hi: self.hi.max(other.hi),
            }
        }
    }

    /// approx_eq reports whether the interval can be transformed into the
    /// given interval by moving each endpoint a small distance.
    /// The empty interval is considered to be positioned arbitrarily on the
    /// real line, so any interval with a small enough length will match
    /// the empty interval.
    pub fn approx_eq(&self, other: &Self) -> bool {
        if self.is_empty() {
            other.len() < 2f64 * EPSILON
        } else if other.is_empty() {
            self.len() < 2f64 * EPSILON
        } else {
            (self.lo - other.lo).abs() <= EPSILON && (self.hi - other.hi).abs() <= EPSILON

        }
    }
}

impl std::ops::Add<f64> for Interval {
    type Output = Interval;
    fn add(self, p: f64) -> Self::Output {
        &self + p
    }
}
impl<'a> std::ops::Add<f64> for &'a Interval {
    type Output = Interval;
    /// returns the interval expanded so that it contains the given point.
    fn add(self, p: f64) -> Self::Output {
        if self.is_empty() {
            Interval { lo: p, hi: p }
        } else if p < self.lo {
            Interval { lo: p, hi: self.hi }
        } else if p > self.hi {
            Interval { lo: self.lo, hi: p }
        } else {
            self.clone()
        }
    }
}

impl std::cmp::PartialEq<Interval> for Interval {
    /// returns true iff the interval contains the same points as other.
    fn eq(&self, other: &Interval) -> bool {
        (self.lo == other.lo && self.hi == other.hi) || (self.is_empty() && other.is_empty())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    macro_rules! I {
        ($lo: expr, $hi: expr) => {
            Interval{lo: $lo, hi: $hi}
        }
    }

    const UNIT: Interval = I!{0., 1.};
    const NEG_UNIT: Interval = I!{-1., 0.};
    const HALF: Interval = I!{0.5, 0.5};
    const ZERO: Interval = I!{0., 0.};

    #[test]
    fn is_empty() {
        assert_eq!(false, UNIT.is_empty());
        assert_eq!(false, HALF.is_empty());
        assert_eq!(true, EMPTY.is_empty());
        assert_eq!(false, ZERO.is_empty());
    }

    #[test]
    fn center() {
        assert_eq!(UNIT.center(), 0.5);
        assert_eq!(NEG_UNIT.center(), -0.5);
        assert_eq!(HALF.center(), 0.5);
    }

    #[test]
    fn length() {
        assert_eq!(UNIT.len(), 1.);
        assert_eq!(NEG_UNIT.len(), 1.);
        assert_eq!(HALF.len(), 0.);
    }

    #[test]
    fn interval_contains() {
        assert_eq!(true, UNIT.contains(0.5));
        assert_eq!(true, UNIT.interior_contains(0.5));

        assert_eq!(true, UNIT.contains(0.));
        assert_eq!(false, UNIT.interior_contains(0.));

        assert_eq!(true, UNIT.contains(1.));
        assert_eq!(false, UNIT.interior_contains(1.));
    }

    fn test_interval_ops(have: &Interval,
                         other: &Interval,
                         contains: bool,
                         interior_contains: bool,
                         intersects: bool,
                         interior_intersects: bool) {
        assert_eq!(contains, have.contains_interval(other));
        assert_eq!(interior_contains, have.interior_contains_interval(other));
        assert_eq!(intersects, have.intersects(other));
        assert_eq!(interior_intersects, have.interior_intersects(other));
    }

    #[test]
    fn interval_operations() {
        test_interval_ops(&EMPTY, &EMPTY, true, true, false, false);
        test_interval_ops(&EMPTY, &UNIT, false, false, false, false);
        test_interval_ops(&UNIT, &HALF, true, true, true, true);
        test_interval_ops(&UNIT, &UNIT, true, false, true, true);
        test_interval_ops(&UNIT, &EMPTY, true, true, false, false);
        test_interval_ops(&UNIT, &NEG_UNIT, false, false, true, false);
    }

    #[test]
    fn intersection() {
        assert_eq!(HALF, UNIT.intersection(&HALF));
        assert_eq!(ZERO, UNIT.intersection(&NEG_UNIT));
        assert_eq!(EMPTY, NEG_UNIT.intersection(&HALF));
        assert_eq!(EMPTY, UNIT.intersection(&EMPTY));
        assert_eq!(EMPTY, EMPTY.intersection(&UNIT));
    }

    fn test_union(x: Interval, y: Interval, want: Interval) {
        assert_eq!(want, x.union(&y));
        assert_eq!(want, y.union(&x));
    }

    #[test]
    fn union() {
        let i_99_100 = Interval { lo: 99., hi: 100. };
        test_union(i_99_100.clone(), EMPTY, i_99_100.clone());
        test_union(I!(5., 3.), I!(0., -2.), EMPTY);
        test_union(UNIT, UNIT, UNIT);
        test_union(UNIT, NEG_UNIT, I!(-1., 1.));
        test_union(HALF, UNIT, UNIT);
    }

    #[test]
    fn add() {
        assert_eq!(I!(5., 5.), EMPTY + 5.);
        assert_eq!(I!(-1., 5.), I!(5., 5.) + -1.);
        assert_eq!(I!(-1., 5.), I!(-1., 5.) + -1.);
        assert_eq!(I!(-1., 6.), I!(-1., 5.) + 6.);
    }

    #[test]
    fn clamp_point() {
        let i = I!(0.1, 0.4);
        assert_eq!(0.3, i.clamp_point(0.3));
        assert_eq!(0.1, i.clamp_point(-7.0));
        assert_eq!(0.4, i.clamp_point(0.6));
    }

    #[test]
    fn expanded() {
        assert_eq!(EMPTY, EMPTY.expanded(0.45));
        assert_eq!(I!(-0.5, 1.5), UNIT.expanded(0.5));
        assert_eq!(I!(0.5, 0.5), UNIT.expanded(-0.5));
        assert_eq!(EMPTY, UNIT.expanded(-0.51));
    }

    fn test_approx_eq(i1: &Interval, i2: &Interval, expected: bool) {
        assert_eq!(expected, i1.approx_eq(&i2));
    }

    #[test]
    fn approx_equal() {
        test_approx_eq(&EMPTY, &EMPTY, true);
        test_approx_eq(&EMPTY, &ZERO, true);
        test_approx_eq(&EMPTY, &I!(1., 1.), true);
        test_approx_eq(&EMPTY, &I!(0., 1.), false);
        test_approx_eq(&EMPTY, &I!(1., 1. + 2. * EPSILON), true);

        test_approx_eq(&I!(1., 1.), &I!(1., 1.), true);
        test_approx_eq(&I!(1., 1.), &I!(1. - EPSILON, 1. - EPSILON), true);
        test_approx_eq(&I!(1., 1.), &I!(1. + EPSILON, 1. + EPSILON), true);
        test_approx_eq(&I!(1., 1.), &I!(1. - 3. * EPSILON, 1.), false);
        test_approx_eq(&I!(1., 1.), &I!(1. - EPSILON, 1. + EPSILON), true);
        test_approx_eq(&ZERO, &I!(1., 1.), false);

        test_approx_eq(&I!(1. - EPSILON, 2. + EPSILON), &I!(1., 2.), false);
        test_approx_eq(&I!(1. + EPSILON, 2. - EPSILON), &I!(1., 2.), true);
        test_approx_eq(&I!(1. - 3. * EPSILON, 2. + EPSILON), &I!(1., 2.), false);
        test_approx_eq(&I!(1. + 3. * EPSILON, 2. - EPSILON), &I!(1., 2.), false);
        test_approx_eq(&I!(1. - EPSILON, 2. + 3. * EPSILON), &I!(1., 2.), false);
        test_approx_eq(&I!(1. + EPSILON, 2. - 3. * EPSILON), &I!(1., 2.), false);
    }
}
<|endoftext|>


<commit_before>use ffi::h5::hsize_t;
use ffi::h5i::{H5I_DATASPACE, hid_t};
use ffi::h5s::{H5S_UNLIMITED, H5Sget_simple_extent_dims, H5Sget_simple_extent_ndims,
               H5Screate_simple};

use error::Result;
use handle::{Handle, ID, get_id_type};
use object::Object;

use std::ptr;
use libc::c_int;

pub type Ix = usize;

pub trait Dimension {
    fn ndim(&self) -> usize;
    fn dims(&self) -> Vec<Ix>;

    fn size(&self) -> usize {
        let dims = self.dims();
        if dims.is_empty() { 0 } else { dims.iter().fold(1, |acc, &el| acc * el) }
    }
}

impl<'a, T: Dimension> Dimension for &'a T {
    fn ndim(&self) -> usize { Dimension::ndim(*self) }
    fn dims(&self) -> Vec<Ix> { Dimension::dims(*self) }
}

impl Dimension for Vec<Ix> {
    fn ndim(&self) -> usize { self.len() }
    fn dims(&self) -> Vec<Ix> { self.clone() }
}

impl Dimension for () {
    fn ndim(&self) -> usize { 0 }
    fn dims(&self) -> Vec<Ix> { vec![] }
}

impl Dimension for Ix {
    fn ndim(&self) -> usize { 1 }
    fn dims(&self) -> Vec<Ix> { vec![*self] }
}

impl Dimension for (Ix,) {
    fn ndim(&self) -> usize { 1 }
    fn dims(&self) -> Vec<Ix> { vec![self.0] }
}

impl Dimension for (Ix, Ix) {
    fn ndim(&self) -> usize { 2 }
    fn dims(&self) -> Vec<Ix> { vec![self.0, self.1] }
}

pub struct Dataspace {
    handle: Handle,
}

impl Dataspace {
    pub fn new<D: Dimension>(d: D) -> Result<Dataspace> {
        let rank = d.ndim();
        let mut dims: Vec<hsize_t> = vec![];
        let mut max_dims: Vec<hsize_t> = vec![];
        for dim in d.dims().iter() {
            dims.push(*dim as hsize_t);
            max_dims.push(H5S_UNLIMITED);
        }
        Dataspace::from_id(h5try!(H5Screate_simple(rank as c_int, dims.as_ptr(),
                                                   max_dims.as_ptr())))
    }
}

impl Dimension for Dataspace {
    fn ndim(&self) -> usize {
        h5call!(H5Sget_simple_extent_ndims(self.id())).unwrap_or(0) as usize
    }

    fn dims(&self) -> Vec<Ix> {
        let ndim = self.ndim();
        if ndim > 0 {
            let mut dims: Vec<hsize_t> = Vec::with_capacity(ndim);
            unsafe { dims.set_len(ndim); }
            if h5call!(H5Sget_simple_extent_dims(self.id(), dims.as_mut_ptr(),
                                                 ptr::null_mut())).is_ok() {
                return dims.iter().cloned().map(|x| x as usize).collect();
            }
        }
        vec![]
    }
}

impl ID for Dataspace {
    fn id(&self) -> hid_t {
        self.handle.id()
    }

    fn from_id(id: hid_t) -> Result<Dataspace> {
        match get_id_type(id) {
            H5I_DATASPACE => Ok(Dataspace { handle: try!(Handle::new(id)) }),
            _             => Err(From::from(format!("Invalid dataspace id: {}", id))),
        }
    }
}

impl Object for Dataspace {}
<commit_msg>Dimension tests<commit_after>use ffi::h5::hsize_t;
use ffi::h5i::{H5I_DATASPACE, hid_t};
use ffi::h5s::{H5S_UNLIMITED, H5Sget_simple_extent_dims, H5Sget_simple_extent_ndims,
               H5Screate_simple};

use error::Result;
use handle::{Handle, ID, get_id_type};
use object::Object;

use std::ptr;
use libc::c_int;

pub type Ix = usize;

pub trait Dimension {
    fn ndim(&self) -> usize;
    fn dims(&self) -> Vec<Ix>;

    fn size(&self) -> Ix {
        let dims = self.dims();
        if dims.is_empty() { 0 } else { dims.iter().fold(1, |acc, &el| acc * el) }
    }
}

impl<'a, T: Dimension> Dimension for &'a T {
    fn ndim(&self) -> usize { Dimension::ndim(*self) }
    fn dims(&self) -> Vec<Ix> { Dimension::dims(*self) }
}

impl Dimension for Vec<Ix> {
    fn ndim(&self) -> usize { self.len() }
    fn dims(&self) -> Vec<Ix> { self.clone() }
}

impl Dimension for () {
    fn ndim(&self) -> usize { 0 }
    fn dims(&self) -> Vec<Ix> { vec![] }
}

impl Dimension for Ix {
    fn ndim(&self) -> usize { 1 }
    fn dims(&self) -> Vec<Ix> { vec![*self] }
}

impl Dimension for (Ix,) {
    fn ndim(&self) -> usize { 1 }
    fn dims(&self) -> Vec<Ix> { vec![self.0] }
}

impl Dimension for (Ix, Ix) {
    fn ndim(&self) -> usize { 2 }
    fn dims(&self) -> Vec<Ix> { vec![self.0, self.1] }
}

pub struct Dataspace {
    handle: Handle,
}

impl Dataspace {
    pub fn new<D: Dimension>(d: D) -> Result<Dataspace> {
        let rank = d.ndim();
        let mut dims: Vec<hsize_t> = vec![];
        let mut max_dims: Vec<hsize_t> = vec![];
        for dim in d.dims().iter() {
            dims.push(*dim as hsize_t);
            max_dims.push(H5S_UNLIMITED);
        }
        Dataspace::from_id(h5try!(H5Screate_simple(rank as c_int, dims.as_ptr(),
                                                   max_dims.as_ptr())))
    }
}

impl Dimension for Dataspace {
    fn ndim(&self) -> usize {
        h5call!(H5Sget_simple_extent_ndims(self.id())).unwrap_or(0) as usize
    }

    fn dims(&self) -> Vec<Ix> {
        let ndim = self.ndim();
        if ndim > 0 {
            let mut dims: Vec<hsize_t> = Vec::with_capacity(ndim);
            unsafe { dims.set_len(ndim); }
            if h5call!(H5Sget_simple_extent_dims(self.id(), dims.as_mut_ptr(),
                                                 ptr::null_mut())).is_ok() {
                return dims.iter().cloned().map(|x| x as usize).collect();
            }
        }
        vec![]
    }
}

impl ID for Dataspace {
    fn id(&self) -> hid_t {
        self.handle.id()
    }

    fn from_id(id: hid_t) -> Result<Dataspace> {
        match get_id_type(id) {
            H5I_DATASPACE => Ok(Dataspace { handle: try!(Handle::new(id)) }),
            _             => Err(From::from(format!("Invalid dataspace id: {}", id))),
        }
    }
}

impl Object for Dataspace {}

#[cfg(test)]
mod tests {
    use super::{Dimension, Ix};

    #[test]
    pub fn test_dimension() {
        fn f<D: Dimension>(d: D) -> (usize, Vec<Ix>, Ix) { (d.ndim(), d.dims(), d.size()) }

        assert_eq!(f(()), (0, vec![], 0));
        assert_eq!(f(&()), (0, vec![], 0));
        assert_eq!(f(2), (1, vec![2], 2));
        assert_eq!(f(&3), (1, vec![3], 3));
        assert_eq!(f((4,)), (1, vec![4], 4));
        assert_eq!(f(&(5,)), (1, vec![5], 5));
        assert_eq!(f((1, 2)), (2, vec![1, 2], 2));
        assert_eq!(f(&(3, 4)), (2, vec![3, 4], 12));
        assert_eq!(f(vec![2, 3]), (2, vec![2, 3], 6));
        assert_eq!(f(&vec![4, 5]), (2, vec![4, 5], 20));
    }
}
<|endoftext|>


<commit_before>//! # Unfinished features
//!
//! - **3.7**: Nonblocking mode:
//!   - Completion, `MPI_Waitany()`, `MPI_Waitall()`, `MPI_Waitsome()`,
//!   `MPI_Testany()`, `MPI_Testall()`, `MPI_Testsome()`, `MPI_Request_get_status()`
//! - **3.8**:
//!   - Cancellation, `MPI_Cancel()`, `MPI_Test_cancelled()`

use std::mem;
use std::marker::PhantomData;

use libc::c_int;

use ffi;
use ffi::{MPI_Request, MPI_Status};

use datatype::traits::*;
use point_to_point::{Status};
use raw::traits::*;

pub mod traits;

/// Wait for an operation to finish.
///
/// # Examples
///
/// See `examples/immediate.rs`
///
/// # Standard section(s)
///
/// 3.7.3
pub trait Wait: RawRequest + Sized {
    /// Will block execution of the calling thread until the associated operation has finished.
    fn wait(mut self) -> Status {
        let mut status: MPI_Status = unsafe { mem::uninitialized() };
        unsafe {
            ffi::MPI_Wait(self.as_raw_mut(), &mut status);
        }
        assert!(self.is_null());
        mem::forget(self);
        Status::from_raw(status)
    }
}

impl<R: RawRequest + Sized> Wait for R { }

/// Test whether an operation has finished.
///
/// # Examples
///
/// See `examples/immediate.rs`
///
/// # Standard section(s)
///
/// 3.7.3
pub trait Test: RawRequest + Sized {
    /// If the operation has finished returns the `Status` otherwise returns the unfinished
    /// `Request`.
    fn test(mut self) -> Result<Status, Self> {
        let mut status: MPI_Status = unsafe { mem::uninitialized() };
        let mut flag: c_int = 0;
        unsafe {
            ffi::MPI_Test(self.as_raw_mut(), &mut flag, &mut status);
        }
        assert!(flag == 0 || self.is_null());
        if flag != 0 {
            mem::forget(self);
            Result::Ok(Status::from_raw(status))
        } else {
            Result::Err(self)
        }
    }
}

impl<R: RawRequest + Sized> Test for R { }

/// Cancel an operation.
///
/// # Examples
///
/// See `examples/immediate.rs`
///
/// # Standard section(s)
///
/// 3.8.4
pub trait Cancel: RawRequest + Sized {
    /// Cancel an operation.
    fn cancel(mut self) {
        unsafe {
            ffi::MPI_Cancel(self.as_raw_mut());
            ffi::MPI_Request_free(self.as_raw_mut());
        }
        assert!(self.is_null());
        mem::forget(self);
    }
}

impl<R: RawRequest + Sized> Cancel for R { }

/// A request object for an non-blocking operation that holds no references
///
/// # Examples
///
/// See `examples/immediate_barrier.rs`
///
/// # Standard section(s)
///
/// 3.7.1
#[must_use]
pub struct Request(MPI_Request);

impl Request {
    /// Construct a request object from the raw MPI type
    pub fn from_raw(request: MPI_Request) -> Request {
        Request(request)
    }
}

impl AsRaw for Request {
    type Raw = MPI_Request;
    unsafe fn as_raw(&self) -> Self::Raw { self.0 }
}

impl AsRawMut for Request {
    unsafe fn as_raw_mut(&mut self) -> *mut <Self as AsRaw>::Raw { &mut (self.0) }
}

impl RawRequest for Request { }

impl Drop for Request {
    fn drop(&mut self) {
        assert!(self.is_null(), "request dropped without ascertaining completion.");
    }
}

/// A request object for a non-blocking operation that holds a reference to an immutable buffer
///
/// # Examples
///
/// See `examples/immediate.rs`
///
/// # Standard section(s)
///
/// 3.7.1
#[must_use]
pub struct ReadRequest<'b, Buf: 'b + Buffer + ?Sized>(MPI_Request, PhantomData<&'b Buf>);

impl<'b, Buf: 'b + Buffer + ?Sized> ReadRequest<'b, Buf> {
    /// Construct a request object from the raw MPI type
    pub fn from_raw(request: MPI_Request, _: &'b Buf) -> ReadRequest<'b, Buf> {
        ReadRequest(request, PhantomData)
    }
}

impl<'b, Buf: 'b + Buffer + ?Sized> AsRaw for ReadRequest<'b, Buf> {
    type Raw = MPI_Request;
    unsafe fn as_raw(&self) -> Self::Raw { self.0 }
}

impl<'b, Buf: 'b + Buffer + ?Sized> AsRawMut for ReadRequest<'b, Buf> {
    unsafe fn as_raw_mut(&mut self) -> *mut <Self as AsRaw>::Raw { &mut (self.0) }
}

impl<'b, Buf: 'b + Buffer + ?Sized> RawRequest for ReadRequest<'b, Buf> { }

impl<'b, Buf: 'b + Buffer + ?Sized> Drop for ReadRequest<'b, Buf> {
    fn drop(&mut self) {
        assert!(self.is_null(), "read request dropped without ascertaining completion.");
    }
}

/// A request object for a non-blocking operation that holds a reference to a mutable buffer
///
/// # Examples
///
/// See `examples/immediate.rs`
///
/// # Standard section(s)
///
/// 3.7.1
#[must_use]
pub struct WriteRequest<'b, Buf: 'b + BufferMut + ?Sized>(MPI_Request, PhantomData<&'b mut Buf>);

impl<'b, Buf: 'b + BufferMut + ?Sized> WriteRequest<'b, Buf> {
    /// Construct a request object from the raw MPI type
    pub fn from_raw(request: MPI_Request, _: &'b Buf) -> WriteRequest<'b, Buf> {
        WriteRequest(request, PhantomData)
    }
}

impl<'b, Buf: 'b + BufferMut + ?Sized> AsRaw for WriteRequest<'b, Buf> {
    type Raw = MPI_Request;
    unsafe fn as_raw(&self) -> Self::Raw { self.0 }
}

impl<'b, Buf: 'b + BufferMut + ?Sized> AsRawMut for WriteRequest<'b, Buf> {
    unsafe fn as_raw_mut(&mut self) -> *mut <Self as AsRaw>::Raw { &mut (self.0) }
}

impl<'b, Buf: 'b + BufferMut + ?Sized> RawRequest for WriteRequest<'b, Buf> { }

impl<'b, Buf: 'b + BufferMut + ?Sized> Drop for WriteRequest<'b, Buf> {
    fn drop(&mut self) {
        assert!(self.is_null(), "write request dropped without ascertaining completion.");
    }
}

/// A request object for a non-blocking operation that holds a reference to a mutable and an
/// immutable buffer
///
/// # Examples
///
/// See `examples/immediate_gather.rs`
///
/// # Standard section(s)
///
/// 3.7.1
#[must_use]
pub struct ReadWriteRequest<'s, 'r, S: 's + Buffer + ?Sized, R: 'r + BufferMut + ?Sized>(MPI_Request, PhantomData<&'s S>, PhantomData<&'r mut R>);

impl<'s, 'r, S: 's + Buffer + ?Sized, R: 'r + BufferMut + ?Sized> ReadWriteRequest<'s, 'r, S, R> {
    /// Construct a request object from the raw MPI type
    pub fn from_raw(request: MPI_Request, _: &'s S, _: &'r R) -> ReadWriteRequest<'s, 'r, S, R> {
        ReadWriteRequest(request, PhantomData, PhantomData)
    }
}

impl<'s, 'r, S: 's + Buffer + ?Sized, R: 'r + BufferMut + ?Sized> AsRaw for ReadWriteRequest<'s, 'r, S, R> {
    type Raw = MPI_Request;
    unsafe fn as_raw(&self) -> Self::Raw { self.0 }
}

impl<'s, 'r, S: 's + Buffer + ?Sized, R: 'r + BufferMut + ?Sized> AsRawMut for ReadWriteRequest<'s, 'r, S, R> {
    unsafe fn as_raw_mut(&mut self) -> *mut <Self as AsRaw>::Raw { &mut (self.0) }
}

impl<'s, 'r, S: 's + Buffer + ?Sized, R: 'r + BufferMut + ?Sized> RawRequest for ReadWriteRequest<'s, 'r, S, R> { }

impl<'s, 'r, S: 's + Buffer + ?Sized, R: 'r + BufferMut + ?Sized> Drop for ReadWriteRequest<'s, 'r, S, R> {
    fn drop(&mut self) {
        assert!(self.is_null(), "read-write request dropped without ascertaining completion.");
    }
}

/// Guard object that waits for the completion of an operation when it is dropped
///
/// # Examples
///
/// See `examples/immediate.rs`
pub struct WaitGuard<Req: RawRequest>(Option<Req>);

impl<Req: RawRequest> Drop for WaitGuard<Req> {
    fn drop(&mut self) {
        let mut req = self.0.take().unwrap();
        unsafe {
            ffi::MPI_Wait(req.as_raw_mut(), ffi::RSMPI_STATUS_IGNORE);
            assert!(req.as_raw() == ffi::RSMPI_REQUEST_NULL);
        }
        mem::forget(req);
    }
}

impl<Req: RawRequest> From<Req> for WaitGuard<Req> {
    fn from(req: Req) -> WaitGuard<Req> {
        WaitGuard(Some(req))
    }
}

/// Guard object that cancels an operation when it is dropped
///
/// # Examples
///
/// See `examples/immediate.rs`
pub struct CancelGuard<Req: RawRequest>(Option<Req>);

impl<Req: RawRequest> Drop for CancelGuard<Req> {
    fn drop(&mut self) {
        let mut req = self.0.take().unwrap();
        unsafe {
            ffi::MPI_Cancel(req.as_raw_mut());
            ffi::MPI_Request_free(req.as_raw_mut());
            assert!(req.as_raw() == ffi::RSMPI_REQUEST_NULL);
        }
        mem::forget(req);
    }
}

impl<Req: RawRequest> From<Req> for CancelGuard<Req> {
    fn from(req: Req) -> CancelGuard<Req> {
        CancelGuard(Some(req))
    }
}
<commit_msg>Do not panic when dropping empty guards.<commit_after>//! # Unfinished features
//!
//! - **3.7**: Nonblocking mode:
//!   - Completion, `MPI_Waitany()`, `MPI_Waitall()`, `MPI_Waitsome()`,
//!   `MPI_Testany()`, `MPI_Testall()`, `MPI_Testsome()`, `MPI_Request_get_status()`
//! - **3.8**:
//!   - Cancellation, `MPI_Cancel()`, `MPI_Test_cancelled()`

use std::mem;
use std::marker::PhantomData;

use libc::c_int;

use ffi;
use ffi::{MPI_Request, MPI_Status};

use datatype::traits::*;
use point_to_point::{Status};
use raw::traits::*;

pub mod traits;

/// Wait for an operation to finish.
///
/// # Examples
///
/// See `examples/immediate.rs`
///
/// # Standard section(s)
///
/// 3.7.3
pub trait Wait: RawRequest + Sized {
    /// Will block execution of the calling thread until the associated operation has finished.
    fn wait(mut self) -> Status {
        let mut status: MPI_Status = unsafe { mem::uninitialized() };
        unsafe {
            ffi::MPI_Wait(self.as_raw_mut(), &mut status);
        }
        assert!(self.is_null());
        mem::forget(self);
        Status::from_raw(status)
    }
}

impl<R: RawRequest + Sized> Wait for R { }

/// Test whether an operation has finished.
///
/// # Examples
///
/// See `examples/immediate.rs`
///
/// # Standard section(s)
///
/// 3.7.3
pub trait Test: RawRequest + Sized {
    /// If the operation has finished returns the `Status` otherwise returns the unfinished
    /// `Request`.
    fn test(mut self) -> Result<Status, Self> {
        let mut status: MPI_Status = unsafe { mem::uninitialized() };
        let mut flag: c_int = 0;
        unsafe {
            ffi::MPI_Test(self.as_raw_mut(), &mut flag, &mut status);
        }
        assert!(flag == 0 || self.is_null());
        if flag != 0 {
            mem::forget(self);
            Result::Ok(Status::from_raw(status))
        } else {
            Result::Err(self)
        }
    }
}

impl<R: RawRequest + Sized> Test for R { }

/// Cancel an operation.
///
/// # Examples
///
/// See `examples/immediate.rs`
///
/// # Standard section(s)
///
/// 3.8.4
pub trait Cancel: RawRequest + Sized {
    /// Cancel an operation.
    fn cancel(mut self) {
        unsafe {
            ffi::MPI_Cancel(self.as_raw_mut());
            ffi::MPI_Request_free(self.as_raw_mut());
        }
        assert!(self.is_null());
        mem::forget(self);
    }
}

impl<R: RawRequest + Sized> Cancel for R { }

/// A request object for an non-blocking operation that holds no references
///
/// # Examples
///
/// See `examples/immediate_barrier.rs`
///
/// # Standard section(s)
///
/// 3.7.1
#[must_use]
pub struct Request(MPI_Request);

impl Request {
    /// Construct a request object from the raw MPI type
    pub fn from_raw(request: MPI_Request) -> Request {
        Request(request)
    }
}

impl AsRaw for Request {
    type Raw = MPI_Request;
    unsafe fn as_raw(&self) -> Self::Raw { self.0 }
}

impl AsRawMut for Request {
    unsafe fn as_raw_mut(&mut self) -> *mut <Self as AsRaw>::Raw { &mut (self.0) }
}

impl RawRequest for Request { }

impl Drop for Request {
    fn drop(&mut self) {
        assert!(self.is_null(), "request dropped without ascertaining completion.");
    }
}

/// A request object for a non-blocking operation that holds a reference to an immutable buffer
///
/// # Examples
///
/// See `examples/immediate.rs`
///
/// # Standard section(s)
///
/// 3.7.1
#[must_use]
pub struct ReadRequest<'b, Buf: 'b + Buffer + ?Sized>(MPI_Request, PhantomData<&'b Buf>);

impl<'b, Buf: 'b + Buffer + ?Sized> ReadRequest<'b, Buf> {
    /// Construct a request object from the raw MPI type
    pub fn from_raw(request: MPI_Request, _: &'b Buf) -> ReadRequest<'b, Buf> {
        ReadRequest(request, PhantomData)
    }
}

impl<'b, Buf: 'b + Buffer + ?Sized> AsRaw for ReadRequest<'b, Buf> {
    type Raw = MPI_Request;
    unsafe fn as_raw(&self) -> Self::Raw { self.0 }
}

impl<'b, Buf: 'b + Buffer + ?Sized> AsRawMut for ReadRequest<'b, Buf> {
    unsafe fn as_raw_mut(&mut self) -> *mut <Self as AsRaw>::Raw { &mut (self.0) }
}

impl<'b, Buf: 'b + Buffer + ?Sized> RawRequest for ReadRequest<'b, Buf> { }

impl<'b, Buf: 'b + Buffer + ?Sized> Drop for ReadRequest<'b, Buf> {
    fn drop(&mut self) {
        assert!(self.is_null(), "read request dropped without ascertaining completion.");
    }
}

/// A request object for a non-blocking operation that holds a reference to a mutable buffer
///
/// # Examples
///
/// See `examples/immediate.rs`
///
/// # Standard section(s)
///
/// 3.7.1
#[must_use]
pub struct WriteRequest<'b, Buf: 'b + BufferMut + ?Sized>(MPI_Request, PhantomData<&'b mut Buf>);

impl<'b, Buf: 'b + BufferMut + ?Sized> WriteRequest<'b, Buf> {
    /// Construct a request object from the raw MPI type
    pub fn from_raw(request: MPI_Request, _: &'b Buf) -> WriteRequest<'b, Buf> {
        WriteRequest(request, PhantomData)
    }
}

impl<'b, Buf: 'b + BufferMut + ?Sized> AsRaw for WriteRequest<'b, Buf> {
    type Raw = MPI_Request;
    unsafe fn as_raw(&self) -> Self::Raw { self.0 }
}

impl<'b, Buf: 'b + BufferMut + ?Sized> AsRawMut for WriteRequest<'b, Buf> {
    unsafe fn as_raw_mut(&mut self) -> *mut <Self as AsRaw>::Raw { &mut (self.0) }
}

impl<'b, Buf: 'b + BufferMut + ?Sized> RawRequest for WriteRequest<'b, Buf> { }

impl<'b, Buf: 'b + BufferMut + ?Sized> Drop for WriteRequest<'b, Buf> {
    fn drop(&mut self) {
        assert!(self.is_null(), "write request dropped without ascertaining completion.");
    }
}

/// A request object for a non-blocking operation that holds a reference to a mutable and an
/// immutable buffer
///
/// # Examples
///
/// See `examples/immediate_gather.rs`
///
/// # Standard section(s)
///
/// 3.7.1
#[must_use]
pub struct ReadWriteRequest<'s, 'r, S: 's + Buffer + ?Sized, R: 'r + BufferMut + ?Sized>(MPI_Request, PhantomData<&'s S>, PhantomData<&'r mut R>);

impl<'s, 'r, S: 's + Buffer + ?Sized, R: 'r + BufferMut + ?Sized> ReadWriteRequest<'s, 'r, S, R> {
    /// Construct a request object from the raw MPI type
    pub fn from_raw(request: MPI_Request, _: &'s S, _: &'r R) -> ReadWriteRequest<'s, 'r, S, R> {
        ReadWriteRequest(request, PhantomData, PhantomData)
    }
}

impl<'s, 'r, S: 's + Buffer + ?Sized, R: 'r + BufferMut + ?Sized> AsRaw for ReadWriteRequest<'s, 'r, S, R> {
    type Raw = MPI_Request;
    unsafe fn as_raw(&self) -> Self::Raw { self.0 }
}

impl<'s, 'r, S: 's + Buffer + ?Sized, R: 'r + BufferMut + ?Sized> AsRawMut for ReadWriteRequest<'s, 'r, S, R> {
    unsafe fn as_raw_mut(&mut self) -> *mut <Self as AsRaw>::Raw { &mut (self.0) }
}

impl<'s, 'r, S: 's + Buffer + ?Sized, R: 'r + BufferMut + ?Sized> RawRequest for ReadWriteRequest<'s, 'r, S, R> { }

impl<'s, 'r, S: 's + Buffer + ?Sized, R: 'r + BufferMut + ?Sized> Drop for ReadWriteRequest<'s, 'r, S, R> {
    fn drop(&mut self) {
        assert!(self.is_null(), "read-write request dropped without ascertaining completion.");
    }
}

/// Guard object that waits for the completion of an operation when it is dropped
///
/// # Examples
///
/// See `examples/immediate.rs`
pub struct WaitGuard<Req: RawRequest>(Option<Req>);

impl<Req: RawRequest> Drop for WaitGuard<Req> {
    fn drop(&mut self) {
        self.0.take().map(|mut req| {
            unsafe {
                ffi::MPI_Wait(req.as_raw_mut(), ffi::RSMPI_STATUS_IGNORE);
            }
            assert!(req.is_null());
            mem::forget(req);
        });
    }
}

impl<Req: RawRequest> From<Req> for WaitGuard<Req> {
    fn from(req: Req) -> WaitGuard<Req> {
        WaitGuard(Some(req))
    }
}

/// Guard object that cancels an operation when it is dropped
///
/// # Examples
///
/// See `examples/immediate.rs`
pub struct CancelGuard<Req: RawRequest>(Option<Req>);

impl<Req: RawRequest> Drop for CancelGuard<Req> {
    fn drop(&mut self) {
        self.0.take().map(|mut req| {
            unsafe {
                ffi::MPI_Cancel(req.as_raw_mut());
                ffi::MPI_Request_free(req.as_raw_mut());
            }
            assert!(req.is_null());
            mem::forget(req);
        });
    }
}

impl<Req: RawRequest> From<Req> for CancelGuard<Req> {
    fn from(req: Req) -> CancelGuard<Req> {
        CancelGuard(Some(req))
    }
}
<|endoftext|>


<commit_before>use std::{ u16, u32 };
use std::num::Int;

use store::Store::{ Array, Bitmap };

pub enum Store {
    Array(Vec<u16>),
    Bitmap([u32; 2048]),
}

fn bitmap_location(index: u16) -> (uint, uint) {
    ((index / (u32::BITS as u16)) as uint, (index % (u32::BITS as u16)) as uint)
}

fn insert_array(vec: &mut Vec<u16>, index: u16) -> bool {
    match vec.binary_search_by(|elem| elem.cmp(&index)) {
        Err(loc) => { vec.insert(loc, index); true },
        _ => false,
    }
}

fn remove_array(vec: &mut Vec<u16>, index: u16) -> bool {
    match vec.binary_search_by(|elem| elem.cmp(&index)) {
        Ok(loc) => { vec.remove(loc); true },
        _ => false,
    }
}

fn insert_bitmap(bits: &mut [u32; 2048], index: u16) -> bool {
    let (key, bit) = bitmap_location(index);
    if bits[key] & (1 << bit) == 0 {
        bits[key] |= 1 << bit;
        true
    } else {
        false
    }
}

fn remove_bitmap(bits: &mut [u32; 2048], index: u16) -> bool {
    let (key, bit) = bitmap_location(index);
    if bits[key] & (1 << bit) != 0 {
        bits[key] &= !(1 << bit);
        true
    } else {
        false
    }
}

fn contains_array(vec: &Vec<u16>, index: u16) -> bool {
    match vec.binary_search_by(|elem| elem.cmp(&index)) {
        Ok(_) => true,
        Err(_) => false,
    }
}

fn contains_bitmap(bits: &[u32; 2048], index: u16) -> bool {
    let (key, bit) = bitmap_location(index);
    bits[key] & (1 << bit) != 0
}

fn bitmap_to_array(bits: &[u32; 2048]) -> Vec<u16> {
    let mut vec = Vec::new();
    for (key, val) in bits.iter().map(|v| *v).enumerate() {
        if val == 0 {
            continue
        }
        for bit in 0..(u32::BITS) {
            if (val & (1 << bit)) != 0 {
                vec.push((key * u32::BITS + bit) as u16);
            }
        }
    }
    vec
}

fn array_to_bitmap(vec: &Vec<u16>) -> [u32; 2048] {
    let mut bits = [0; 2048];
    for index in vec.iter() {
        let (key, bit) = bitmap_location(*index);
        bits[key] |= 1 << bit;
    }
    bits
}

fn is_disjoint_array(vec1: &Vec<u16>, vec2: &Vec<u16>) -> bool {
    let (mut i1, mut i2) = (vec1.iter(), vec2.iter());
    let (mut value1, mut value2) = (i1.next(), i2.next());
    loop {
        match (value1, value2) {
            (None, _) | (_, None) => return true,
            (v1, v2) if v1 == v2 => return false,
            (v1, v2) if v1 < v2 => value1 = i1.next(),
            (v1, v2) if v1 > v2 => value2 = i2.next(),
            (_, _) => panic!(),
        }
    }
}

fn is_disjoint_bitmap(bits1: &[u32; 2048], bits2: &[u32; 2048]) -> bool {
    for (index1, index2) in bits1.iter().zip(bits2.iter()) {
        if *index1 & *index2 != 0 {
            return false;
        }
    }
    return true;
}

fn is_disjoint_array_bitmap(vec: &Vec<u16>, bits: &[u32; 2048]) -> bool {
    for index in vec.iter() {
        if contains_bitmap(bits, *index) {
            return false;
        }
    }
    return true;
}

fn is_subset_array(vec1: &Vec<u16>, vec2: &Vec<u16>) -> bool {
    let (mut i1, mut i2) = (vec1.iter(), vec2.iter());
    let (mut value1, mut value2) = (i1.next(), i2.next());
    loop {
        match (value1, value2) {
            (None, _) => return true,
            (_, None) => return false,
            (v1, v2) if v1 == v2 => {
                value1 = i1.next();
                value2 = i2.next();
            },
            (v1, v2) if v1 < v2 => return false,
            (v1, v2) if v1 > v2 => value2 = i2.next(),
            (_, _) => panic!(),
        }
    }
}

fn is_subset_bitmap(bits1: &[u32; 2048], bits2: &[u32; 2048]) -> bool {
    for (index1, index2) in bits1.iter().zip(bits2.iter()) {
        if *index1 & *index2 != *index1 {
            return false;
        }
    }
    return true;
}

fn is_subset_array_bitmap(vec: &Vec<u16>, bits: &[u32; 2048]) -> bool {
    for index in vec.iter() {
        if !contains_bitmap(bits, *index) {
            return false;
        }
    }
    return true;
}

fn union_with_array(vec1: &mut Vec<u16>, vec2: &Vec<u16>) {
    for index in vec2.iter() {
        insert_array(vec1, *index);
    }
}

fn union_with_bitmap(bits1: &mut [u32; 2048], bits2: &[u32; 2048]) {
    for (index1, index2) in bits1.iter_mut().zip(bits2.iter()) {
        *index1 |= *index2;
    }
}

fn union_with_bitmap_array(bits: &mut [u32; 2048], vec: &Vec<u16>) {
    for index in vec.iter() {
        insert_bitmap(bits, *index);
    }
}

fn union_with(mut this: &mut Store, other: &Store) {
    match (&mut this, other) {
        (& &Array(ref mut vec1), &Array(ref vec2)) => union_with_array(vec1, vec2),
        (& &Bitmap(ref mut bits1), &Bitmap(ref bits2)) => union_with_bitmap(bits1, bits2),
        (& &Bitmap(ref mut bits), &Array(ref vec)) => union_with_bitmap_array(bits, vec),
        (& &Array(_), &Bitmap(_)) => {
            *this = this.to_bitmap();
            this.union_with(other);
        },
    }
}

fn intersect_with_array(vec1: &mut Vec<u16>, vec2: &Vec<u16>) {
    let mut i1 = 0u;
    let mut iter2 = vec2.iter();
    let mut current2 = iter2.next();
    while i1 < vec1.len() {
        match (vec1[i1], current2) {
            (_, None) => { vec1.remove(i1); },
            (ref val1, Some(val2)) if val1 < val2 => { vec1.remove(i1); },
            (ref val1, Some(val2)) if val1 > val2 => { current2 = iter2.next(); },
            (ref val1, Some(val2)) if val1 == val2 => {
                i1 += 1;
                current2 = iter2.next();
            },
            _ => panic!("Should not be possible to get here"),
        }
    }
}

fn intersect_with_bitmap(bits1: &mut [u32; 2048], bits2: &[u32; 2048]) {
    for (index1, index2) in bits1.iter_mut().zip(bits2.iter()) {
        *index1 &= *index2;
    }
}

fn intersect_with_array_bitmap(vec: &mut Vec<u16>, bits: &[u32; 2048]) {
    let mut i = 0;
    while i < vec.len() {
        if contains_bitmap(bits, vec[i]) {
            i += 1;
        } else {
            vec.remove(i);
        }
    }
}

fn intersect_with(mut this: &mut Store, other: &Store) {
    match (&mut this, other) {
        (& &Array(ref mut vec1), &Array(ref vec2)) => intersect_with_array(vec1, vec2),
        (& &Bitmap(ref mut bits1), &Bitmap(ref bits2)) => intersect_with_bitmap(bits1, bits2),
        (& &Array(ref mut vec), &Bitmap(ref bits)) => intersect_with_array_bitmap(vec, bits),
        (& &Bitmap(..), &Array(..)) => {
            *this = this.to_array();
            this.intersect_with(other);
        },
    }
}

fn symmetric_difference_with(mut this: &mut Store, other: &Store) {
    match (&mut this, other) {
        (_, &Array(ref vec2)) => {
            for index in vec2.iter() {
                if this.contains(*index) {
                    this.remove(*index);
                } else {
                    this.insert(*index);
                }
            }
        },
        (& &Bitmap(ref mut bits1), &Bitmap(ref bits2)) => {
            for (index1, index2) in bits1.iter_mut().zip(bits2.iter()) {
                *index1 ^= *index2;
            }
        },
        (& &Array(..), &Bitmap(..)) => {
            *this = this.to_bitmap();
            this.symmetric_difference_with(other);
        },
    }
}

impl Store {
    pub fn insert(&mut self, index: u16) -> bool {
        match self {
            &Array(ref mut vec) => insert_array(vec, index),
            &Bitmap(ref mut bits) => insert_bitmap(bits, index),
        }
    }

    pub fn remove(&mut self, index: u16) -> bool {
        match self {
            &Array(ref mut vec) => remove_array(vec, index),
            &Bitmap(ref mut bits) => remove_bitmap(bits, index),
        }
    }

    pub fn contains(&self, index: u16) -> bool {
        match self {
            &Array(ref vec) => contains_array(vec, index),
            &Bitmap(ref bits) => contains_bitmap(bits, index),
        }
    }

    pub fn is_disjoint(&self, other: &Self) -> bool {
        match (self, other) {
            (&Array(ref vec1), &Array(ref vec2)) => is_disjoint_array(vec1, vec2),
            (&Bitmap(ref bits1), &Bitmap(ref bits2)) => is_disjoint_bitmap(bits1, bits2),
            (&Array(ref vec), &Bitmap(ref bits)) => is_disjoint_array_bitmap(vec, bits),
            (&Bitmap(ref bits), &Array(ref vec)) => is_disjoint_array_bitmap(vec, bits),
        }
    }

    pub fn is_subset(&self, other: &Self) -> bool {
        match (self, other) {
            (&Array(ref vec1), &Array(ref vec2)) => is_subset_array(vec1, vec2),
            (&Bitmap(ref bits1), &Bitmap(ref bits2)) => is_subset_bitmap(bits1, bits2),
            (&Array(ref vec), &Bitmap(ref bits)) => is_subset_array_bitmap(vec, bits),
            (&Bitmap(..), &Array(..)) => false,
        }
    }

    pub fn to_array(&self) -> Self {
        match self {
            &Array(_) => panic!("Cannot convert array to array"),
            &Bitmap(ref bits) => Array(bitmap_to_array(bits)),
        }
    }

    pub fn to_bitmap(&self) -> Self {
        match self {
            &Array(ref vec) => Bitmap(array_to_bitmap(vec)),
            &Bitmap(_) => panic!("Cannot convert bitmap to bitmap"),
        }
    }

    pub fn union_with(&mut self, other: &Self) {
        union_with(self, other);
    }

    pub fn intersect_with(&mut self, other: &Self) {
        intersect_with(self, other);
    }

    pub fn difference_with(&mut self, other: &Self) {
        match (self, other) {
            (ref mut this @ _, &Array(ref vec2)) => {
                for index in vec2.iter() {
                    this.remove(*index);
                }
            },
            (&Bitmap(ref mut bits1), &Bitmap(ref bits2)) => {
                for (index1, index2) in bits1.iter_mut().zip(bits2.iter()) {
                    *index1 &= !*index2;
                }
            },
            (&Array(ref mut vec), &Bitmap(ref bits)) => {
                for i in range(0, vec.len()).rev() {
                    if contains_bitmap(bits, vec[i]) {
                        vec.remove(i);
                    }
                }
            },
        }
    }

    pub fn symmetric_difference_with(&mut self, other: &Self) {
        symmetric_difference_with(self, other);
    }

    pub fn len(&self) -> u16 {
        match self {
            &Array(ref vec) => vec.len() as u16,
            &Bitmap(ref bits) => {
                let mut len = 0;
                for bit in bits.iter() {
                    len += bit.count_ones()
                }
                len as u16
            },
        }
    }

    pub fn min(&self) -> u16 {
        match self {
            &Array(ref vec) => vec[0],
            &Bitmap(ref bits) => {
                for (index, bit) in bits.iter().enumerate() {
                    if *bit != 0 {
                        return (index * u32::BITS + bit.leading_zeros()) as u16;
                    }
                }
                return u16::MIN;
            },
        }
    }

    pub fn max(&self) -> u16 {
        match self {
            &Array(ref vec) => vec[vec.len() - 1],
            &Bitmap(ref bits) => {
                for (index, bit) in bits.iter().enumerate().rev() {
                    if *bit != 0 {
                        return ((index + 1) * u32::BITS - bit.trailing_zeros()) as u16;
                    }
                }
                return u16::MAX;
            },
        }
    }
}

impl PartialEq for Store {
    fn eq(&self, other: &Store) -> bool {
        match (self, other) {
            (&Array(ref vec1), &Array(ref vec2)) => {
                vec1 == vec2
            },
            (&Bitmap(ref bits1), &Bitmap(ref bits2)) => {
                bits1.iter().zip(bits2.iter()).map(|(i1, i2)| i1 == i2).fold(true, |acc, n| acc & n)
            },
            _ => false,
        }
    }
}

impl Clone for Store {
    fn clone(&self) -> Self {
        match self {
            &Array(ref vec) => Array(vec.clone()),
            &Bitmap(ref bits) => {
                let mut new_bits = [0u32; 2048];
                for (i1, i2) in new_bits.iter_mut().zip(bits.iter()) {
                    *i1 = *i2;
                }
                Bitmap(new_bits)
            },
        }
    }
}
<commit_msg>Rearrange store, move methods inline<commit_after>use std::{ u16, u32 };
use std::num::Int;

use store::Store::{ Array, Bitmap };

pub enum Store {
    Array(Vec<u16>),
    Bitmap([u32; 2048]),
}

impl Store {
    pub fn insert(&mut self, index: u16) -> bool {
        match self {
            &Array(ref mut vec) => {
                match vec.binary_search_by(|elem| elem.cmp(&index)) {
                    Err(loc) => { vec.insert(loc, index); true },
                    Ok(..) => false,
                }
            },
            &Bitmap(ref mut bits) => {
                let (key, bit) = bitmap_location(index);
                if bits[key] & (1 << bit) == 0 {
                    bits[key] |= 1 << bit;
                    true
                } else {
                    false
                }
            },
        }
    }

    pub fn remove(&mut self, index: u16) -> bool {
        match self {
            &Array(ref mut vec) => {
                match vec.binary_search_by(|elem| elem.cmp(&index)) {
                    Ok(loc) => { vec.remove(loc); true },
                    Err(..) => false,
                }
            },
            &Bitmap(ref mut bits) => {
                let (key, bit) = bitmap_location(index);
                if bits[key] & (1 << bit) != 0 {
                    bits[key] &= !(1 << bit);
                    true
                } else {
                    false
                }
            },
        }
    }

    pub fn contains(&self, index: u16) -> bool {
        match self {
            &Array(ref vec) => {
                match vec.binary_search_by(|elem| elem.cmp(&index)) {
                    Ok(..) => true,
                    Err(..) => false,
                }
            },
            &Bitmap(ref bits) => {
                let (key, bit) = bitmap_location(index);
                bits[key] & (1 << bit) != 0
            },
        }
    }

    pub fn is_disjoint(&self, other: &Self) -> bool {
        match (self, other) {
            (&Array(ref vec1), &Array(ref vec2)) => {
                let (mut i1, mut i2) = (vec1.iter(), vec2.iter());
                let (mut value1, mut value2) = (i1.next(), i2.next());
                loop {
                    match (value1, value2) {
                        (None, _) | (_, None) => return true,
                        (v1, v2) if v1 == v2 => return false,
                        (v1, v2) if v1 < v2 => value1 = i1.next(),
                        (v1, v2) if v1 > v2 => value2 = i2.next(),
                        (_, _) => panic!(),
                    }
                }
            },
            (&Bitmap(ref bits1), &Bitmap(ref bits2)) => {
                for (index1, index2) in bits1.iter().zip(bits2.iter()) {
                    if *index1 & *index2 != 0 {
                        return false;
                    }
                }
                return true;
            },
            (&Array(ref vec), store @ &Bitmap(..)) | (store @ &Bitmap(..), &Array(ref vec)) => {
                for &index in vec.iter() {
                    if store.contains(index) {
                        return false;
                    }
                }
                return true;
            },
        }
    }

    pub fn is_subset(&self, other: &Self) -> bool {
        match (self, other) {
            (&Array(ref vec1), &Array(ref vec2)) => {
                let (mut i1, mut i2) = (vec1.iter(), vec2.iter());
                let (mut value1, mut value2) = (i1.next(), i2.next());
                loop {
                    match (value1, value2) {
                        (None, _) => return true,
                        (_, None) => return false,
                        (v1, v2) if v1 == v2 => {
                            value1 = i1.next();
                            value2 = i2.next();
                        },
                        (v1, v2) if v1 < v2 => return false,
                        (v1, v2) if v1 > v2 => value2 = i2.next(),
                        (_, _) => panic!(),
                    }
                }
            },
            (&Bitmap(ref bits1), &Bitmap(ref bits2)) => {
                for (index1, index2) in bits1.iter().zip(bits2.iter()) {
                    if *index1 & *index2 != *index1 {
                        return false;
                    }
                }
                return true;
            },
            (&Array(ref vec), store @ &Bitmap(..)) => {
                for &index in vec.iter() {
                    if !store.contains(index) {
                        return false;
                    }
                }
                return true;
            },
            (&Bitmap(..), &Array(..)) => false,
        }
    }

    pub fn to_array(&self) -> Self {
        match self {
            &Array(..) => panic!("Cannot convert array to array"),
            &Bitmap(ref bits) => {
                let mut vec = Vec::new();
                for (key, val) in bits.iter().map(|v| *v).enumerate() {
                    if val == 0 {
                        continue
                    }
                    for bit in 0..(u32::BITS) {
                        if (val & (1 << bit)) != 0 {
                            vec.push((key * u32::BITS + bit) as u16);
                        }
                    }
                }
                Array(vec)
            },
        }
    }

    pub fn to_bitmap(&self) -> Self {
        match self {
            &Array(ref vec) => {
                let mut bits = [0; 2048];
                for index in vec.iter() {
                    let (key, bit) = bitmap_location(*index);
                    bits[key] |= 1 << bit;
                }
                Bitmap(bits)
            },
            &Bitmap(..) => panic!("Cannot convert bitmap to bitmap"),
        }
    }

    pub fn union_with(&mut self, other: &Self) {
        match (self, other) {
            (ref mut this, &Array(ref vec)) => {
                for &index in vec.iter() {
                    this.insert(index);
                }
            },
            (&Bitmap(ref mut bits1), &Bitmap(ref bits2)) => {
                for (index1, &index2) in bits1.iter_mut().zip(bits2.iter()) {
                    *index1 |= index2;
                }
            },
            (this @ &Array(..), &Bitmap(..)) => {
                *this = this.to_bitmap();
                this.union_with(other);
            },
        }
    }

    pub fn intersect_with(&mut self, other: &Self) {
        match (self, other) {
            (&Array(ref mut vec1), &Array(ref vec2)) => {
                let mut i1 = 0u;
                let mut iter2 = vec2.iter();
                let mut current2 = iter2.next();
                while i1 < vec1.len() {
                    match (vec1[i1], current2) {
                        (_, None) => { vec1.remove(i1); },
                        (ref val1, Some(val2)) if val1 < val2 => { vec1.remove(i1); },
                        (ref val1, Some(val2)) if val1 > val2 => { current2 = iter2.next(); },
                        (ref val1, Some(val2)) if val1 == val2 => {
                            i1 += 1;
                            current2 = iter2.next();
                        },
                        _ => panic!("Should not be possible to get here"),
                    }
                }
            },
            (&Bitmap(ref mut bits1), &Bitmap(ref bits2)) => {
                for (index1, index2) in bits1.iter_mut().zip(bits2.iter()) {
                    *index1 &= *index2;
                }
            },
            (&Array(ref mut vec), store @ &Bitmap(..)) => {
                let mut i = 0;
                while i < vec.len() {
                    if store.contains(vec[i]) {
                        i += 1;
                    } else {
                        vec.remove(i);
                    }
                }
            },
            (this @ &Bitmap(..), &Array(..)) => {
                *this = this.to_array();
                this.intersect_with(other);
            },
        }
    }

    pub fn difference_with(&mut self, other: &Self) {
        match (self, other) {
            (ref mut this @ _, &Array(ref vec2)) => {
                for index in vec2.iter() {
                    this.remove(*index);
                }
            },
            (&Bitmap(ref mut bits1), &Bitmap(ref bits2)) => {
                for (index1, index2) in bits1.iter_mut().zip(bits2.iter()) {
                    *index1 &= !*index2;
                }
            },
            (&Array(ref mut vec), store @ &Bitmap(..)) => {
                for i in range(0, vec.len()).rev() {
                    if store.contains(vec[i]) {
                        vec.remove(i);
                    }
                }
            },
        }
    }

    pub fn symmetric_difference_with(&mut self, other: &Self) {
        match (self, other) {
            (ref mut this, &Array(ref vec2)) => {
                for index in vec2.iter() {
                    if this.contains(*index) {
                        this.remove(*index);
                    } else {
                        this.insert(*index);
                    }
                }
            },
            (&Bitmap(ref mut bits1), &Bitmap(ref bits2)) => {
                for (index1, index2) in bits1.iter_mut().zip(bits2.iter()) {
                    *index1 ^= *index2;
                }
            },
            (this @ &Array(..), &Bitmap(..)) => {
                *this = this.to_bitmap();
                this.symmetric_difference_with(other);
            },
        }
    }

    pub fn len(&self) -> u16 {
        match self {
            &Array(ref vec) => vec.len() as u16,
            &Bitmap(ref bits) => {
                let mut len = 0;
                for bit in bits.iter() {
                    len += bit.count_ones()
                }
                len as u16
            },
        }
    }

    pub fn min(&self) -> u16 {
        match self {
            &Array(ref vec) => vec[0],
            &Bitmap(ref bits) => {
                for (index, bit) in bits.iter().enumerate() {
                    if *bit != 0 {
                        return (index * u32::BITS + bit.leading_zeros()) as u16;
                    }
                }
                return u16::MIN;
            },
        }
    }

    pub fn max(&self) -> u16 {
        match self {
            &Array(ref vec) => vec[vec.len() - 1],
            &Bitmap(ref bits) => {
                for (index, bit) in bits.iter().enumerate().rev() {
                    if *bit != 0 {
                        return ((index + 1) * u32::BITS - bit.trailing_zeros()) as u16;
                    }
                }
                return u16::MAX;
            },
        }
    }
}

impl PartialEq for Store {
    fn eq(&self, other: &Store) -> bool {
        match (self, other) {
            (&Array(ref vec1), &Array(ref vec2)) => {
                vec1 == vec2
            },
            (&Bitmap(ref bits1), &Bitmap(ref bits2)) => {
                bits1.iter().zip(bits2.iter()).map(|(i1, i2)| i1 == i2).fold(true, |acc, n| acc & n)
            },
            _ => false,
        }
    }
}

impl Clone for Store {
    fn clone(&self) -> Self {
        match self {
            &Array(ref vec) => Array(vec.clone()),
            &Bitmap(ref bits) => {
                let mut new_bits = [0u32; 2048];
                for (i1, &i2) in new_bits.iter_mut().zip(bits.iter()) {
                    *i1 = i2;
                }
                Bitmap(new_bits)
            },
        }
    }
}

#[inline]
fn bitmap_location(index: u16) -> (uint, uint) {
    ((index / (u32::BITS as u16)) as uint, (index % (u32::BITS as u16)) as uint)
}
<|endoftext|>