<commit_before>/// For Huffman codes used in the Deflate spec, is seems that the length of a code is at most 9 bits.
/// For this simple use case, we don't need/want to deal with type parameters.
type Symbol = u16;

#[derive(Debug, Clone, PartialEq)]
struct Node {
	left: Option<Box<Tree>>,
	right: Option<Box<Tree>>,
}

#[derive(Debug, Clone, PartialEq)]
enum Tree {
	Leaf(Symbol),
	Inner(Node),
}

impl Tree {
	fn new() -> Tree {
		Tree::Inner(Node{
			left: None,
			right: None,
		})
	}

	fn insert(&mut self, code: Vec<bool>, symbol: Symbol) {
		if code.len() == 1 {
			if code[0] {
				*self = Tree::Inner(Node{
					left: match self {
						&mut Tree::Inner(Node{
							ref left,
							right: _,
						}) => left.clone(),
						&mut Tree::Leaf(_) => unreachable!(),
					},
					right: Some(Box::new(Tree::Leaf(symbol))),
				});
			} else {
				*self = Tree::Inner(Node{
					left: Some(Box::new(Tree::Leaf(symbol))),
					right: match self {
						&mut Tree::Inner(Node{
							left: _,
							ref right,
						}) => right.clone(),
						&mut Tree::Leaf(_) => unreachable!(),
					},
				});
			}
		} else {
			if code[0] {
				match self {
					&mut Tree::Inner(Node{
						left: _,
						ref mut right,
					}) => {
						match right {
							&mut None => *right = Some(Box::new(Tree::new())),
							&mut Some(_) => {
								// Nothing to do
							},
						};
						// Now we can be sure that right is a subtree. So we can delegate to it.

						match right {
							&mut Some(ref mut boxed_tree) => (*boxed_tree).insert(code[1..].to_vec(), symbol),
							_ => unreachable!(),
						};
					},
					&mut Tree::Leaf(_) => unreachable!(),
				}
			} else {
				match self {
					&mut Tree::Inner(Node{
						ref mut left,
						right: _,
					}) => {
						match left {
							&mut None => *left = Some(Box::new(Tree::new())),
							&mut Some(_) => {
								// Nothing to do
							},
						};
						// Now we can be sure that left is a subtree. So we can delegate to it.

						match left {
							&mut Some(ref mut boxed_tree) => (*boxed_tree).insert(code[1..].to_vec(), symbol),
							_ => unreachable!(),
						};
					},
					&mut Tree::Leaf(_) => unreachable!(),
				}
			}
		}
	}
}

mod tests {
	#[test]
	fn should_create_empty_tree() {
		use super::{Tree, Node};
		use super::Tree::Inner;

		assert_eq!(Tree::new(), Inner(Node{
			left: None,
			right: None,
		}));
	}

	#[test]
	fn should_insert_first_level_leaf_on_left() {
		use super::{Tree, Node};
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![false], 666);

		assert_eq!(Inner(Node{
			left: Some(Box::new(Leaf(666))),
			right: None,
		}), tree);
	}

	#[test]
	fn should_insert_first_level_leaf_on_right() {
		use super::{Tree, Node};
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![true], 666);

		assert_eq!(Inner(Node{
			left: None,
			right: Some(Box::new(Leaf(666))),
		}), tree);
	}

	#[test]
	fn should_insert_first_level_leaf_on_left_then_on_right() {
		use super::{Tree, Node};
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![false], 667);
		tree.insert(vec![true], 666);

		assert_eq!(Inner(Node{
			left: Some(Box::new(Leaf(667))),
			right: Some(Box::new(Leaf(666))),
		}), tree);
	}

	#[test]
	fn should_insert_first_level_leaf_on_right_then_on_left() {
		use super::{Tree, Node};
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![true], 666);
		tree.insert(vec![false], 667);

		assert_eq!(Inner(Node{
			left: Some(Box::new(Leaf(667))),
			right: Some(Box::new(Leaf(666))),
		}), tree);
	}

	#[test]
	fn should_insert_second_level_leaf_left_right() {
		use super::{Tree, Node};
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![false, true], 6666);

		assert_eq!(Inner(Node{
			left: Some(Box::new(Inner(Node{
				left: None,
				right: Some(Box::new(Leaf(6666))),
			}))),
			right: None
		}), tree);
	}

	#[test]
	fn should_insert_second_level_leaf_right_left() {
		use super::{Tree, Node};
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![true, false], 6666);

		assert_eq!(Inner(Node{
			left: None,
			right: Some(Box::new(Inner(Node{
				left: Some(Box::new(Leaf(6666))),
				right: None,
			}))),
		}), tree);
	}
}

<commit_msg>ADD: bit-by-bit lookup<commit_after>/// For Huffman codes used in the Deflate spec, is seems that the length of a code is at most 9 bits.
/// For this simple use case, we don't need/want to deal with type parameters.
pub type Symbol = u16;

#[derive(Debug, Clone, PartialEq)]
pub struct Node {
	left: Option<Box<Tree>>,
	right: Option<Box<Tree>>,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Tree {
	Leaf(Symbol),
	Inner(Node),
}

impl Tree {
	fn new() -> Tree {
		Tree::Inner(Node{
			left: None,
			right: None,
		})
	}

	fn insert(&mut self, code: Vec<bool>, symbol: Symbol) {
		if code.len() == 1 {
			if code[0] {
				*self = Tree::Inner(Node{
					left: match self {
						&mut Tree::Inner(Node{
							ref left,
							right: _,
						}) => left.clone(),
						&mut Tree::Leaf(_) => unreachable!(),
					},
					right: Some(Box::new(Tree::Leaf(symbol))),
				});
			} else {
				*self = Tree::Inner(Node{
					left: Some(Box::new(Tree::Leaf(symbol))),
					right: match self {
						&mut Tree::Inner(Node{
							left: _,
							ref right,
						}) => right.clone(),
						&mut Tree::Leaf(_) => unreachable!(),
					},
				});
			}
		} else {
			if code[0] {
				match self {
					&mut Tree::Inner(Node{
						left: _,
						ref mut right,
					}) => {
						match right {
							&mut None => *right = Some(Box::new(Tree::new())),
							&mut Some(_) => {
								// Nothing to do
							},
						};
						// Now we can be sure that right is a subtree. So we can delegate to it.

						match right {
							&mut Some(ref mut boxed_tree) => (*boxed_tree).insert(code[1..].to_vec(), symbol),
							_ => unreachable!(),
						};
					},
					&mut Tree::Leaf(_) => unreachable!(),
				}
			} else {
				match self {
					&mut Tree::Inner(Node{
						ref mut left,
						right: _,
					}) => {
						match left {
							&mut None => *left = Some(Box::new(Tree::new())),
							&mut Some(_) => {
								// Nothing to do
							},
						};
						// Now we can be sure that left is a subtree. So we can delegate to it.

						match left {
							&mut Some(ref mut boxed_tree) => (*boxed_tree).insert(code[1..].to_vec(), symbol),
							_ => unreachable!(),
						};
					},
					&mut Tree::Leaf(_) => unreachable!(),
				}
			}
		}
	}

	fn lookup(&mut self, c: bool) -> Option<Tree> {
		match self {
			&mut Tree::Leaf(_) => None,
			&mut Tree::Inner(Node{
				ref left,
				ref right
			}) =>
				if c {
					match *right {
						Some(ref boxed_tree) => Some((**boxed_tree).clone()),
						None => None,
					}
				} else {
					match *left {
						Some(ref boxed_tree) => Some((**boxed_tree).clone()),
						None => None,
					}
				}
		}
	}
}

mod tests {
	#[test]
	fn should_create_empty_tree() {
		use super::{Tree, Node};
		use super::Tree::Inner;

		assert_eq!(Tree::new(), Inner(Node{
			left: None,
			right: None,
		}));
	}

	#[test]
	fn should_insert_first_level_leaf_on_left() {
		use super::{Tree, Node};
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![false], 666);

		assert_eq!(Inner(Node{
			left: Some(Box::new(Leaf(666))),
			right: None,
		}), tree);
	}

	#[test]
	fn should_insert_first_level_leaf_on_right() {
		use super::{Tree, Node};
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![true], 666);

		assert_eq!(Inner(Node{
			left: None,
			right: Some(Box::new(Leaf(666))),
		}), tree);
	}

	#[test]
	fn should_insert_first_level_leaf_on_left_then_on_right() {
		use super::{Tree, Node};
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![false], 667);
		tree.insert(vec![true], 666);

		assert_eq!(Inner(Node{
			left: Some(Box::new(Leaf(667))),
			right: Some(Box::new(Leaf(666))),
		}), tree);
	}

	#[test]
	fn should_insert_first_level_leaf_on_right_then_on_left() {
		use super::{Tree, Node};
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![true], 666);
		tree.insert(vec![false], 667);

		assert_eq!(Inner(Node{
			left: Some(Box::new(Leaf(667))),
			right: Some(Box::new(Leaf(666))),
		}), tree);
	}

	#[test]
	fn should_insert_second_level_leaf_left_right() {
		use super::{Tree, Node};
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![false, true], 6666);

		assert_eq!(Inner(Node{
			left: Some(Box::new(Inner(Node{
				left: None,
				right: Some(Box::new(Leaf(6666))),
			}))),
			right: None
		}), tree);
	}

	#[test]
	fn should_insert_second_level_leaf_right_left() {
		use super::{Tree, Node};
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![true, false], 6666);

		assert_eq!(Inner(Node{
			left: None,
			right: Some(Box::new(Inner(Node{
				left: Some(Box::new(Leaf(6666))),
				right: None,
			}))),
		}), tree);
	}

	#[test]
	fn should_lookup_first_level_leaf_left() {
		use super::{ Tree, Node };
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![true, false], 6666);
		tree.insert(vec![false], 666);
		tree.insert(vec![true, true], 6667);

		assert_eq!(Some(Leaf(666)), tree.lookup(false));
	}

	#[test]
	fn should_lookup_first_level_leaf_right() {
		use super::{ Tree, Node };
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![false, false], 6666);
		tree.insert(vec![true], 666);
		tree.insert(vec![false, true], 6667);

		assert_eq!(Some(Leaf(666)), tree.lookup(true));
	}

	#[test]
	fn should_lookup_first_level_node_left() {
		use super::{ Tree, Node };
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![false, false], 6666);
		tree.insert(vec![true], 666);
		tree.insert(vec![false, true], 6667);

		assert_eq!(Some(Inner(Node{
			left: Some(Box::new(Tree::Leaf(6666))),
			right: Some(Box::new(Tree::Leaf(6667))),
		})), tree.lookup(false));
	}

	#[test]
	fn should_result_in_none() {
		use super::{ Tree, Node };
		use super::Tree::{ Inner, Leaf };

		let mut tree = Tree::new();
		tree.insert(vec![true], 666);

		assert_eq!(None, tree.lookup(false));
	}
}

<|endoftext|>


<commit_before>use std::string::String;
use js_types::js_obj::JsObjStruct;
use js_types::js_str::JsStrStruct;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use uuid::Uuid;

pub struct JsT {
    pub binding: Option<String>,
    pub uuid: Uuid,
    pub t: JsType,
}

impl JsT {
    pub fn new(t: JsType) -> JsT {
        JsT {
            binding: None,
            uuid: Uuid::new_v4(),
            t: t,
        }
    }

    pub fn bind(binding: &str, t: JsType) -> JsT {
        JsT {
            binding: Some(String::from(binding)),
            uuid: Uuid::new_v4(),
            t: t,
        }
    }
}

impl PartialEq for JsT {
    fn eq(&self, other: &Self) -> bool {
        self.uuid == other.uuid
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsT {}

impl Hash for JsT {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.uuid.hash(state);
    }

    fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher {
        for ref d in data {
            d.uuid.hash(state);
        }
    }
}

pub enum JsType {
    JsUndef,
    JsNull,
    JsNum(f64),
    JsSym(String),
    JsStr(JsStrStruct),
    JsObj(JsObjStruct),
}

// `array`
pub type JsArr = Vec<JsType>;
<commit_msg>Make JsT Clone and add gc_flag enum field<commit_after>use std::string::String;
use js_types::js_obj::JsObjStruct;
use js_types::js_str::JsStrStruct;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use uuid::Uuid;

#[derive(Clone)]
pub enum Marking {
    White,
    Grey,
    Black,
}

#[derive(Clone)]
pub struct JsT {
    pub binding: Option<String>,
    pub gc_flag: Marking,
    pub uuid: Uuid,
    pub t: JsType,
}

impl JsT {
    pub fn new(t: JsType) -> JsT {
        JsT {
            binding: None,
            gc_flag: Marking::Grey,
            uuid: Uuid::new_v4(),
            t: t,
        }
    }

    pub fn bind(binding: &str, t: JsType) -> JsT {
        JsT {
            binding: Some(String::from(binding)),
            gc_flag: Marking::Grey,
            uuid: Uuid::new_v4(),
            t: t,
        }
    }
}

impl PartialEq for JsT {
    fn eq(&self, other: &Self) -> bool {
        self.uuid == other.uuid
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsT {}

impl Hash for JsT {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.uuid.hash(state);
    }

    fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher {
        for ref d in data {
            d.uuid.hash(state);
        }
    }
}

#[derive(Clone)]
pub enum JsType {
    JsUndef,
    JsNull,
    JsNum(f64),
    JsSym(String),
    JsStr(JsStrStruct),
    JsObj(JsObjStruct),
}

// `array`
pub type JsArr = Vec<JsType>;
<|endoftext|>


<commit_before>use super::super::{Grid, Coord};
use super::*;

use rand::Rng;

pub fn generate<R: Rng>(has_clue: &Grid<bool>, dic: &Dictionary, rng: &mut R) -> Option<Grid<Clue>> {
    let height = has_clue.height();
    let width = has_clue.width();

    let mut answer = Grid::new(height, width, -1);
    let mut current_total_cands = (height * width * 9);
    for y in 0..height {
        for x in 0..width {
            if !has_clue[Coord { y: y, x: x }] {
                answer[Coord { y: y, x: x }] = (y + x) % MAX_VAL + 1;
            }
        }
    }

    let field_shape = FieldShape::new(has_clue);
    let n_step = height * width * 10;
    let mut temperature = 10.0f64;

    for step in 0..n_step {
        let mut move_cand: Vec<Vec<(i32, i32, i32, i32)>> = vec![];

        let mut grp_has_val = vec![0; field_shape.group_to_cells.len()];
        for y in 0..height {
            for x in 0..width {
                let loc = Coord { y: y, x: x };
                if has_clue[loc] {
                    continue;
                }
                let (g1, g2) = field_shape.cell_to_groups[loc];
                grp_has_val[g1 as usize] |= 1 << answer[loc];
                grp_has_val[g2 as usize] |= 1 << answer[loc];
            }
        }
        for y in 0..height {
            for x in 0..width {
                let loc = Coord { y: y, x: x };
                if has_clue[loc] {
                    continue;
                }
                let (g1, g2) = field_shape.cell_to_groups[loc];
                for c in 1..MAX_VAL {
                    if answer[loc] == c {
                        continue;
                    }
                    if (grp_has_val[g1 as usize] & (1 << c)) != 0 {
                        continue;
                    }
                    if (grp_has_val[g2 as usize] & (1 << c)) != 0 {
                        continue;
                    }
                    move_cand.push(vec![(y, x, answer[loc], c)]);
                }
            }
        }

        rng.shuffle(&mut move_cand);

        for cand in &move_cand {
            for &(y, x, _, c) in cand {
                answer[Coord { y: y, x: x }] = c;
            }
            let problem = answer_to_problem(&answer);
            let mut field = Field::new(&problem, dic);
            field.check_all();

            if field.inconsistent() {
                unreachable!();
            }
            if field.solved() {
                return Some(problem);
            }

            let total_cands = field.total_cands() as i32;
            if current_total_cands > total_cands || rng.next_f64() < ((current_total_cands - total_cands) as f64 / temperature).exp() {
                current_total_cands = total_cands;
                break;
            } else {
                for &(y, x, old, _) in cand {
                    answer[Coord { y: y, x: x }] = old;
                }
            }
        }

        temperature *= 0.995;
    }

    None
}
<commit_msg>Kakuro: enhance generator<commit_after>use super::super::{Grid, Coord};
use super::*;

use rand::Rng;

pub fn generate<R: Rng>(has_clue: &Grid<bool>, dic: &Dictionary, rng: &mut R) -> Option<Grid<Clue>> {
    let height = has_clue.height();
    let width = has_clue.width();

    let mut answer = Grid::new(height, width, -1);
    let mut current_total_cands = (height * width * 9);
    for y in 0..height {
        for x in 0..width {
            if !has_clue[Coord { y: y, x: x }] {
                answer[Coord { y: y, x: x }] = (y + x) % MAX_VAL + 1;
            }
        }
    }

    let field_shape = FieldShape::new(has_clue);
    let n_step = height * width * 10;
    let mut temperature = 10.0f64;

    for step in 0..n_step {
        let mut move_cand: Vec<Vec<(usize, i32, i32)>> = vec![];

        let mut grp_val_loc = vec![[-1; (MAX_VAL + 1) as usize]; field_shape.group_to_cells.len()];
        for y in 0..height {
            for x in 0..width {
                let loc = Coord { y: y, x: x };
                if has_clue[loc] {
                    continue;
                }
                let (g1, g2) = field_shape.cell_to_groups[loc];
                grp_val_loc[g1 as usize][answer[loc] as usize] = has_clue.index(loc) as i32;
                grp_val_loc[g2 as usize][answer[loc] as usize] = has_clue.index(loc) as i32;
            }
        }
        for y in 0..height {
            for x in 0..width {
                let loc = Coord { y: y, x: x };
                let c = has_clue.index(loc);
                if has_clue[loc] {
                    continue;
                }
                let (g1, g2) = field_shape.cell_to_groups[loc];
                for v in 1..(MAX_VAL + 1) {
                    if answer[loc] == v {
                        continue;
                    }
                    match (grp_val_loc[g1 as usize][v as usize], grp_val_loc[g2 as usize][v as usize]) {
                        (-1, -1) => move_cand.push(vec![(c, answer[loc], v)]),
                        (c1, -1) => {
                            if answer[loc] < v && grp_val_loc[field_shape.cell_to_groups[c1 as usize].1 as usize][answer[loc] as usize] == -1 {
                                move_cand.push(vec![
                                    (c, answer[loc], v),
                                    (c1 as usize, v, answer[loc]),
                                ]);
                            }
                        },
                        (-1, c2) => {
                            if answer[loc] < v && grp_val_loc[field_shape.cell_to_groups[c2 as usize].0 as usize][answer[loc] as usize] == -1 {
                                move_cand.push(vec![
                                    (c, answer[loc], v),
                                    (c2 as usize, v, answer[loc]),
                                ]);
                            }
                        },
                        (c1, c2) => {
                            if grp_val_loc[field_shape.cell_to_groups[c1 as usize].1 as usize][answer[loc] as usize] == -1 &&
                               grp_val_loc[field_shape.cell_to_groups[c2 as usize].0 as usize][answer[loc] as usize] == -1 {
                                move_cand.push(vec![
                                    (c, answer[loc], v),
                                    (c1 as usize, v, answer[loc]),
                                    (c2 as usize, v, answer[loc]),
                                ]);
                            }
                        },
                    }
                }
            }
        }

        rng.shuffle(&mut move_cand);

        for cand in &move_cand {
            for &(id, _, c) in cand {
                answer[id] = c;
            }
            let problem = answer_to_problem(&answer);
            let mut field = Field::new(&problem, dic);
            field.check_all();

            if field.inconsistent() {
                unreachable!();
            }
            if field.solved() {
                return Some(problem);
            }

            let total_cands = field.total_cands() as i32;
            if current_total_cands > total_cands || rng.next_f64() < ((current_total_cands - total_cands) as f64 / temperature).exp() {
                current_total_cands = total_cands;
                break;
            } else {
                for &(id, old, _) in cand {
                    answer[id] = old;
                }
            }
        }

        temperature *= 0.995;
    }

    None
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Native os-thread management
//!
//! This modules contains bindings necessary for managing OS-level threads.
//! These functions operate outside of the rust runtime, creating threads
//! which are not used for scheduling in any way.

#![allow(non_camel_case_types)]

use cast;
use kinds::Send;
use libc;
use ops::Drop;
use option::{Option, Some, None};
use uint;

type StartFn = extern "C" fn(*libc::c_void) -> imp::rust_thread_return;

/// This struct represents a native thread's state. This is used to join on an
/// existing thread created in the join-able state.
pub struct Thread<T> {
    native: imp::rust_thread,
    joined: bool,
    packet: ~Option<T>,
}

static DEFAULT_STACK_SIZE: uint = 1024 * 1024;

// This is the starting point of rust os threads. The first thing we do
// is make sure that we don't trigger __morestack (also why this has a
// no_split_stack annotation), and then we extract the main function
// and invoke it.
#[no_split_stack]
extern fn thread_start(main: *libc::c_void) -> imp::rust_thread_return {
    use rt::stack;
    unsafe {
        stack::record_stack_bounds(0, uint::MAX);
        let f: ~proc() = cast::transmute(main);
        (*f)();
        cast::transmute(0 as imp::rust_thread_return)
    }
}

// There are two impl blocks b/c if T were specified at the top then it's just a
// pain to specify a type parameter on Thread::spawn (which doesn't need the
// type parameter).
impl Thread<()> {

    /// Starts execution of a new OS thread.
    ///
    /// This function will not wait for the thread to join, but a handle to the
    /// thread will be returned.
    ///
    /// Note that the handle returned is used to acquire the return value of the
    /// procedure `main`. The `join` function will wait for the thread to finish
    /// and return the value that `main` generated.
    ///
    /// Also note that the `Thread` returned will *always* wait for the thread
    /// to finish executing. This means that even if `join` is not explicitly
    /// called, when the `Thread` falls out of scope its destructor will block
    /// waiting for the OS thread.
    pub fn start<T: Send>(main: proc():Send -> T) -> Thread<T> {
        Thread::start_stack(DEFAULT_STACK_SIZE, main)
    }

    /// Performs the same functionality as `start`, but specifies an explicit
    /// stack size for the new thread.
    pub fn start_stack<T: Send>(stack: uint, main: proc():Send -> T) -> Thread<T> {

        // We need the address of the packet to fill in to be stable so when
        // `main` fills it in it's still valid, so allocate an extra ~ box to do
        // so.
        let packet = ~None;
        let packet2: *mut Option<T> = unsafe {
            *cast::transmute::<&~Option<T>, **mut Option<T>>(&packet)
        };
        let main = proc() unsafe { *packet2 = Some(main()); };
        let native = unsafe { imp::create(stack, ~main) };

        Thread {
            native: native,
            joined: false,
            packet: packet,
        }
    }

    /// This will spawn a new thread, but it will not wait for the thread to
    /// finish, nor is it possible to wait for the thread to finish.
    ///
    /// This corresponds to creating threads in the 'detached' state on unix
    /// systems. Note that platforms may not keep the main program alive even if
    /// there are detached thread still running around.
    pub fn spawn(main: proc():Send) {
        Thread::spawn_stack(DEFAULT_STACK_SIZE, main)
    }

    /// Performs the same functionality as `spawn`, but explicitly specifies a
    /// stack size for the new thread.
    pub fn spawn_stack(stack: uint, main: proc():Send) {
        unsafe {
            let handle = imp::create(stack, ~main);
            imp::detach(handle);
        }
    }

    /// Relinquishes the CPU slot that this OS-thread is currently using,
    /// allowing another thread to run for awhile.
    pub fn yield_now() {
        unsafe { imp::yield_now(); }
    }
}

impl<T: Send> Thread<T> {
    /// Wait for this thread to finish, returning the result of the thread's
    /// calculation.
    pub fn join(mut self) -> T {
        assert!(!self.joined);
        unsafe { imp::join(self.native) };
        self.joined = true;
        assert!(self.packet.is_some());
        self.packet.take_unwrap()
    }
}

#[unsafe_destructor]
impl<T: Send> Drop for Thread<T> {
    fn drop(&mut self) {
        // This is required for correctness. If this is not done then the thread
        // would fill in a return box which no longer exists.
        if !self.joined {
            unsafe { imp::join(self.native) };
        }
    }
}

#[cfg(windows)]
mod imp {
    use cast;
    use cmp;
    use kinds::Send;
    use libc;
    use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T, BOOL,
                                       LPVOID, DWORD, LPDWORD, HANDLE};
    use ptr;
    use rt::stack::RED_ZONE;

    pub type rust_thread = HANDLE;
    pub type rust_thread_return = DWORD;

    pub unsafe fn create(stack: uint, p: ~proc():Send) -> rust_thread {
        let arg: *mut libc::c_void = cast::transmute(p);
        // FIXME On UNIX, we guard against stack sizes that are too small but
        // that's because pthreads enforces that stacks are at least
        // PTHREAD_STACK_MIN bytes big.  Windows has no such lower limit, it's
        // just that below a certain threshold you can't do anything useful.
        // That threshold is application and architecture-specific, however.
        // For now, the only requirement is that it's big enough to hold the
        // red zone.  Round up to the next 64 kB because that's what the NT
        // kernel does, might as well make it explicit.  With the current
        // 20 kB red zone, that makes for a 64 kB minimum stack.
        let stack_size = (cmp::max(stack, RED_ZONE) + 0xfffe) & (-0xfffe - 1);
        CreateThread(ptr::mut_null(), stack_size as libc::size_t,
                     super::thread_start, arg, 0, ptr::mut_null())
    }

    pub unsafe fn join(native: rust_thread) {
        use libc::consts::os::extra::INFINITE;
        WaitForSingleObject(native, INFINITE);
    }

    pub unsafe fn detach(native: rust_thread) {
        assert!(libc::CloseHandle(native) != 0);
    }

    pub unsafe fn yield_now() {
        // This function will return 0 if there are no other threads to execute,
        // but this also means that the yield was useless so this isn't really a
        // case that needs to be worried about.
        SwitchToThread();
    }

    extern "system" {
        fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES,
                        dwStackSize: SIZE_T,
                        lpStartAddress: super::StartFn,
                        lpParameter: LPVOID,
                        dwCreationFlags: DWORD,
                        lpThreadId: LPDWORD) -> HANDLE;
        fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
        fn SwitchToThread() -> BOOL;
    }
}

#[cfg(unix)]
mod imp {
    use cast;
    use cmp;
    use kinds::Send;
    use libc::consts::os::posix01::{PTHREAD_CREATE_JOINABLE, PTHREAD_STACK_MIN};
    use libc;
    use mem;
    use os;
    use ptr;
    use rt::stack::RED_ZONE;

    pub type rust_thread = libc::pthread_t;
    pub type rust_thread_return = *u8;

    pub unsafe fn create(stack: uint, p: ~proc():Send) -> rust_thread {
        let mut native: libc::pthread_t = mem::uninit();
        let mut attr: libc::pthread_attr_t = mem::uninit();
        assert_eq!(pthread_attr_init(&mut attr), 0);
        assert_eq!(pthread_attr_setdetachstate(&mut attr,
                                               PTHREAD_CREATE_JOINABLE), 0);

        // Reserve room for the red zone, the runtime's stack of last resort.
        let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as uint);
        match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
            0 => {
            },
            libc::EINVAL => {
                // EINVAL means |stack_size| is either too small or not a
                // multiple of the system page size.  Because it's definitely
                // >= PTHREAD_STACK_MIN, it must be an alignment issue.
                // Round up to the neareast page and try again.
                let page_size = os::page_size();
                let stack_size = (stack_size + page_size - 1) & (-(page_size - 1) - 1);
                assert_eq!(pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t), 0);
            },
            errno => {
                // This cannot really happen.
                fail!("pthread_attr_setstacksize() error: {} ({})", os::last_os_error(), errno);
            },
        };

        let arg: *libc::c_void = cast::transmute(p);
        assert_eq!(pthread_create(&mut native, &attr,
                                  super::thread_start, arg), 0);
        native
    }

    pub unsafe fn join(native: rust_thread) {
        assert_eq!(pthread_join(native, ptr::null()), 0);
    }

    pub unsafe fn detach(native: rust_thread) {
        assert_eq!(pthread_detach(native), 0);
    }

    #[cfg(target_os = "macos")]
    #[cfg(target_os = "android")]
    pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); }

    #[cfg(not(target_os = "macos"), not(target_os = "android"))]
    pub unsafe fn yield_now() { assert_eq!(pthread_yield(), 0); }

    // glibc >= 2.15 has a __pthread_get_minstack() function that returns
    // PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
    // storage.  We need that information to avoid blowing up when a small stack
    // is created in an application with big thread-local storage requirements.
    // See #6233 for rationale and details.
    //
    // Link weakly to the symbol for compatibility with older versions of glibc.
    // Assumes that we've been dynamically linked to libpthread but that is
    // currently always the case.  Note that you need to check that the symbol
    // is non-null before calling it!
    #[cfg(target_os = "linux")]
    fn min_stack_size(attr: *libc::pthread_attr_t) -> libc::size_t {
        use ptr::RawPtr;
        type F = extern "C" unsafe fn(*libc::pthread_attr_t) -> libc::size_t;
        extern {
            #[linkage = "extern_weak"]
            static __pthread_get_minstack: *();
        }
        if __pthread_get_minstack.is_null() {
            PTHREAD_STACK_MIN
        } else {
            unsafe { cast::transmute::<*(), F>(__pthread_get_minstack)(attr) }
        }
    }

    // __pthread_get_minstack() is marked as weak but extern_weak linkage is
    // not supported on OS X, hence this kludge...
    #[cfg(not(target_os = "linux"))]
    fn min_stack_size(_: *libc::pthread_attr_t) -> libc::size_t {
        PTHREAD_STACK_MIN
    }

    extern {
        fn pthread_create(native: *mut libc::pthread_t,
                          attr: *libc::pthread_attr_t,
                          f: super::StartFn,
                          value: *libc::c_void) -> libc::c_int;
        fn pthread_join(native: libc::pthread_t,
                        value: **libc::c_void) -> libc::c_int;
        fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
        fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
                                     stack_size: libc::size_t) -> libc::c_int;
        fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
                                       state: libc::c_int) -> libc::c_int;
        fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;

        #[cfg(target_os = "macos")]
        #[cfg(target_os = "android")]
        fn sched_yield() -> libc::c_int;
        #[cfg(not(target_os = "macos"), not(target_os = "android"))]
        fn pthread_yield() -> libc::c_int;
    }
}

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

    #[test]
    fn smoke() { Thread::start(proc (){}).join(); }

    #[test]
    fn data() { assert_eq!(Thread::start(proc () { 1 }).join(), 1); }

    #[test]
    fn detached() { Thread::spawn(proc () {}) }

    #[test]
    fn small_stacks() {
        assert_eq!(42, Thread::start_stack(0, proc () 42).join());
        assert_eq!(42, Thread::start_stack(1, proc () 42).join());
    }
}

<commit_msg>auto merge of #13457 : alexcrichton/rust/issue-13420, r=thestinger<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Native os-thread management
//!
//! This modules contains bindings necessary for managing OS-level threads.
//! These functions operate outside of the rust runtime, creating threads
//! which are not used for scheduling in any way.

#![allow(non_camel_case_types)]

use cast;
use kinds::Send;
use libc;
use ops::Drop;
use option::{Option, Some, None};
use uint;

type StartFn = extern "C" fn(*libc::c_void) -> imp::rust_thread_return;

/// This struct represents a native thread's state. This is used to join on an
/// existing thread created in the join-able state.
pub struct Thread<T> {
    native: imp::rust_thread,
    joined: bool,
    packet: ~Option<T>,
}

static DEFAULT_STACK_SIZE: uint = 1024 * 1024;

// This is the starting point of rust os threads. The first thing we do
// is make sure that we don't trigger __morestack (also why this has a
// no_split_stack annotation), and then we extract the main function
// and invoke it.
#[no_split_stack]
extern fn thread_start(main: *libc::c_void) -> imp::rust_thread_return {
    use rt::stack;
    unsafe {
        stack::record_stack_bounds(0, uint::MAX);
        let f: ~proc() = cast::transmute(main);
        (*f)();
        cast::transmute(0 as imp::rust_thread_return)
    }
}

// There are two impl blocks b/c if T were specified at the top then it's just a
// pain to specify a type parameter on Thread::spawn (which doesn't need the
// type parameter).
impl Thread<()> {

    /// Starts execution of a new OS thread.
    ///
    /// This function will not wait for the thread to join, but a handle to the
    /// thread will be returned.
    ///
    /// Note that the handle returned is used to acquire the return value of the
    /// procedure `main`. The `join` function will wait for the thread to finish
    /// and return the value that `main` generated.
    ///
    /// Also note that the `Thread` returned will *always* wait for the thread
    /// to finish executing. This means that even if `join` is not explicitly
    /// called, when the `Thread` falls out of scope its destructor will block
    /// waiting for the OS thread.
    pub fn start<T: Send>(main: proc():Send -> T) -> Thread<T> {
        Thread::start_stack(DEFAULT_STACK_SIZE, main)
    }

    /// Performs the same functionality as `start`, but specifies an explicit
    /// stack size for the new thread.
    pub fn start_stack<T: Send>(stack: uint, main: proc():Send -> T) -> Thread<T> {

        // We need the address of the packet to fill in to be stable so when
        // `main` fills it in it's still valid, so allocate an extra ~ box to do
        // so.
        let packet = ~None;
        let packet2: *mut Option<T> = unsafe {
            *cast::transmute::<&~Option<T>, **mut Option<T>>(&packet)
        };
        let main = proc() unsafe { *packet2 = Some(main()); };
        let native = unsafe { imp::create(stack, ~main) };

        Thread {
            native: native,
            joined: false,
            packet: packet,
        }
    }

    /// This will spawn a new thread, but it will not wait for the thread to
    /// finish, nor is it possible to wait for the thread to finish.
    ///
    /// This corresponds to creating threads in the 'detached' state on unix
    /// systems. Note that platforms may not keep the main program alive even if
    /// there are detached thread still running around.
    pub fn spawn(main: proc():Send) {
        Thread::spawn_stack(DEFAULT_STACK_SIZE, main)
    }

    /// Performs the same functionality as `spawn`, but explicitly specifies a
    /// stack size for the new thread.
    pub fn spawn_stack(stack: uint, main: proc():Send) {
        unsafe {
            let handle = imp::create(stack, ~main);
            imp::detach(handle);
        }
    }

    /// Relinquishes the CPU slot that this OS-thread is currently using,
    /// allowing another thread to run for awhile.
    pub fn yield_now() {
        unsafe { imp::yield_now(); }
    }
}

impl<T: Send> Thread<T> {
    /// Wait for this thread to finish, returning the result of the thread's
    /// calculation.
    pub fn join(mut self) -> T {
        assert!(!self.joined);
        unsafe { imp::join(self.native) };
        self.joined = true;
        assert!(self.packet.is_some());
        self.packet.take_unwrap()
    }
}

#[unsafe_destructor]
impl<T: Send> Drop for Thread<T> {
    fn drop(&mut self) {
        // This is required for correctness. If this is not done then the thread
        // would fill in a return box which no longer exists.
        if !self.joined {
            unsafe { imp::join(self.native) };
        }
    }
}

#[cfg(windows)]
mod imp {
    use cast;
    use cmp;
    use kinds::Send;
    use libc;
    use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T, BOOL,
                                       LPVOID, DWORD, LPDWORD, HANDLE};
    use ptr;
    use rt::stack::RED_ZONE;

    pub type rust_thread = HANDLE;
    pub type rust_thread_return = DWORD;

    pub unsafe fn create(stack: uint, p: ~proc():Send) -> rust_thread {
        let arg: *mut libc::c_void = cast::transmute(p);
        // FIXME On UNIX, we guard against stack sizes that are too small but
        // that's because pthreads enforces that stacks are at least
        // PTHREAD_STACK_MIN bytes big.  Windows has no such lower limit, it's
        // just that below a certain threshold you can't do anything useful.
        // That threshold is application and architecture-specific, however.
        // For now, the only requirement is that it's big enough to hold the
        // red zone.  Round up to the next 64 kB because that's what the NT
        // kernel does, might as well make it explicit.  With the current
        // 20 kB red zone, that makes for a 64 kB minimum stack.
        let stack_size = (cmp::max(stack, RED_ZONE) + 0xfffe) & (-0xfffe - 1);
        CreateThread(ptr::mut_null(), stack_size as libc::size_t,
                     super::thread_start, arg, 0, ptr::mut_null())
    }

    pub unsafe fn join(native: rust_thread) {
        use libc::consts::os::extra::INFINITE;
        WaitForSingleObject(native, INFINITE);
    }

    pub unsafe fn detach(native: rust_thread) {
        assert!(libc::CloseHandle(native) != 0);
    }

    pub unsafe fn yield_now() {
        // This function will return 0 if there are no other threads to execute,
        // but this also means that the yield was useless so this isn't really a
        // case that needs to be worried about.
        SwitchToThread();
    }

    extern "system" {
        fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES,
                        dwStackSize: SIZE_T,
                        lpStartAddress: super::StartFn,
                        lpParameter: LPVOID,
                        dwCreationFlags: DWORD,
                        lpThreadId: LPDWORD) -> HANDLE;
        fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
        fn SwitchToThread() -> BOOL;
    }
}

#[cfg(unix)]
mod imp {
    use cast;
    use cmp;
    use kinds::Send;
    use libc::consts::os::posix01::{PTHREAD_CREATE_JOINABLE, PTHREAD_STACK_MIN};
    use libc;
    use mem;
    use os;
    use ptr;
    use rt::stack::RED_ZONE;

    pub type rust_thread = libc::pthread_t;
    pub type rust_thread_return = *u8;

    pub unsafe fn create(stack: uint, p: ~proc():Send) -> rust_thread {
        let mut native: libc::pthread_t = mem::uninit();
        let mut attr: libc::pthread_attr_t = mem::uninit();
        assert_eq!(pthread_attr_init(&mut attr), 0);
        assert_eq!(pthread_attr_setdetachstate(&mut attr,
                                               PTHREAD_CREATE_JOINABLE), 0);

        // Reserve room for the red zone, the runtime's stack of last resort.
        let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as uint);
        match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
            0 => {
            },
            libc::EINVAL => {
                // EINVAL means |stack_size| is either too small or not a
                // multiple of the system page size.  Because it's definitely
                // >= PTHREAD_STACK_MIN, it must be an alignment issue.
                // Round up to the neareast page and try again.
                let page_size = os::page_size();
                let stack_size = (stack_size + page_size - 1) & (-(page_size - 1) - 1);
                assert_eq!(pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t), 0);
            },
            errno => {
                // This cannot really happen.
                fail!("pthread_attr_setstacksize() error: {} ({})", os::last_os_error(), errno);
            },
        };

        let arg: *libc::c_void = cast::transmute(p);
        assert_eq!(pthread_create(&mut native, &attr,
                                  super::thread_start, arg), 0);
        assert_eq!(pthread_attr_destroy(&mut attr), 0);
        native
    }

    pub unsafe fn join(native: rust_thread) {
        assert_eq!(pthread_join(native, ptr::null()), 0);
    }

    pub unsafe fn detach(native: rust_thread) {
        assert_eq!(pthread_detach(native), 0);
    }

    #[cfg(target_os = "macos")]
    #[cfg(target_os = "android")]
    pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); }

    #[cfg(not(target_os = "macos"), not(target_os = "android"))]
    pub unsafe fn yield_now() { assert_eq!(pthread_yield(), 0); }

    // glibc >= 2.15 has a __pthread_get_minstack() function that returns
    // PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
    // storage.  We need that information to avoid blowing up when a small stack
    // is created in an application with big thread-local storage requirements.
    // See #6233 for rationale and details.
    //
    // Link weakly to the symbol for compatibility with older versions of glibc.
    // Assumes that we've been dynamically linked to libpthread but that is
    // currently always the case.  Note that you need to check that the symbol
    // is non-null before calling it!
    #[cfg(target_os = "linux")]
    fn min_stack_size(attr: *libc::pthread_attr_t) -> libc::size_t {
        use ptr::RawPtr;
        type F = extern "C" unsafe fn(*libc::pthread_attr_t) -> libc::size_t;
        extern {
            #[linkage = "extern_weak"]
            static __pthread_get_minstack: *();
        }
        if __pthread_get_minstack.is_null() {
            PTHREAD_STACK_MIN
        } else {
            unsafe { cast::transmute::<*(), F>(__pthread_get_minstack)(attr) }
        }
    }

    // __pthread_get_minstack() is marked as weak but extern_weak linkage is
    // not supported on OS X, hence this kludge...
    #[cfg(not(target_os = "linux"))]
    fn min_stack_size(_: *libc::pthread_attr_t) -> libc::size_t {
        PTHREAD_STACK_MIN
    }

    extern {
        fn pthread_create(native: *mut libc::pthread_t,
                          attr: *libc::pthread_attr_t,
                          f: super::StartFn,
                          value: *libc::c_void) -> libc::c_int;
        fn pthread_join(native: libc::pthread_t,
                        value: **libc::c_void) -> libc::c_int;
        fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
        fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
        fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
                                     stack_size: libc::size_t) -> libc::c_int;
        fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
                                       state: libc::c_int) -> libc::c_int;
        fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;

        #[cfg(target_os = "macos")]
        #[cfg(target_os = "android")]
        fn sched_yield() -> libc::c_int;
        #[cfg(not(target_os = "macos"), not(target_os = "android"))]
        fn pthread_yield() -> libc::c_int;
    }
}

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

    #[test]
    fn smoke() { Thread::start(proc (){}).join(); }

    #[test]
    fn data() { assert_eq!(Thread::start(proc () { 1 }).join(), 1); }

    #[test]
    fn detached() { Thread::spawn(proc () {}) }

    #[test]
    fn small_stacks() {
        assert_eq!(42, Thread::start_stack(0, proc () 42).join());
        assert_eq!(42, Thread::start_stack(1, proc () 42).join());
    }
}

<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate genomic_fx;
extern crate bio;

use std::collections::HashMap;

use bio::utils::{Interval, Strand};
use test::Bencher;

use genomic_fx::{ExonFeature, ExonFeatureKind, EBuilder, TBuilder, GBuilder};
use ExonFeatureKind::*;

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

    #[bench]
    fn ebuilder_no_features(b: &mut Bencher) {
        b.iter(|| {
            EBuilder::new("chrT", 100, 500)
                .strand(Strand::Forward)
                .build()
        });
    }

    #[bench]
    fn ebuiler_5_features(b: &mut Bencher) {
        b.iter(|| {
            EBuilder::new("chrT", 100, 300)
                .strand(Strand::Forward)
                .features(vec![
                    ExonFeature {
                        interval: Interval::new(100..150).unwrap(),
                        kind: UTR5,
                    },
                    ExonFeature {
                        interval: Interval::new(150..153).unwrap(),
                        kind: StartCodon { frame: Some(0) },
                    },
                    ExonFeature {
                        interval: Interval::new(150..300).unwrap(),
                        kind: CDS { frame: Some(0) },
                    },
                    ExonFeature {
                        interval: Interval::new(300..303).unwrap(),
                        kind: StopCodon { frame: Some(0) },
                    },
                    ExonFeature {
                        interval: Interval::new(300..500).unwrap(),
                        kind: UTR3,
                    },
                ])
                .build()
        });
    }

    #[bench]
    fn tbuilder_1_exon_no_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .exon_coords(vec![(100, 10000)], None)
                .build()
        });
    }

    #[bench]
    fn tbuilder_1_exon_1_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .exon_coords(vec![(100, 10000)], Some(200, 9500))
                .build()
        });
    }

    #[bench]
    fn tbuilder_12_exons_no_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .exon_coords(
                    vec![
                        (100, 300), (400, 500), (700, 1000),
                        (1100, 1300), (1400, 1500), (1700, 2000),
                        (2100, 2300), (2400, 2500), (2700, 3000),
                        (3000, 6000), (7000, 8000), (9000, 10000),
                    ])
                .build()
        });
    }

    #[bench]
    fn tbuilder_12_exons_with_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .exon_coords(
                    vec![
                        (100, 300), (400, 500), (700, 1000),
                        (1100, 1300), (1400, 1500), (1700, 2000),
                        (2100, 2300), (2400, 2500), (2700, 3000),
                        (3000, 6000), (7000, 8000), (9000, 10000),
                    ], Some(200, 9500))
                .build()
        });
    }

    #[bench]
    fn gbuilder_no_transcripts(b: &mut Bencher) {
        b.iter(|| {
            GBuilder::new("chrT", 100, 20000)
                .strand(Strand::Forward)
                .id("gx01")
                .build()
        });
    }

    #[bench]
    fn gbuilder_3_transcripts_with_cds(b: &mut Bencher) {
        b.iter(|| {
            let mut coords = HashMap::new();
            coords.insert(
                "trx01".to_owned(),
                ((100, 10000),
                vec![
                    (100, 300), (400, 500), (700, 1000),
                    (1100, 1300), (1400, 1500), (1700, 2000),
                    (2100, 2300), (2400, 2500), (2700, 3000),
                    (3000, 6000), (7000, 8000), (9000, 10000)],
                Some((200, 9500))));
            coords.insert(
                "trx02".to_owned(),
                ((100, 10000),
                vec![
                    (100, 300), (400, 500), (700, 1000),
                    (1100, 1300), (1400, 1500), (1700, 2000),
                    (2100, 2300), (2400, 2500), (2700, 3000),
                    (3000, 6000), (7000, 8000), (9000, 10000)],
                Some((200, 9500))));
            coords.insert(
                "trx03".to_owned(),
                ((100, 10000),
                vec![
                    (100, 300), (400, 500), (700, 1000),
                    (1100, 1300), (1400, 1500), (1700, 2000),
                    (2100, 2300), (2400, 2500), (2700, 3000),
                    (3000, 6000), (7000, 8000), (9000, 10000)],
                Some((200, 9500))));
            GBuilder::new("chrT", 100, 20000)
                .strand(Strand::Forward)
                .id("gx01")
                .transcript_coords(coords)
                .build()
        });
    }
}
<commit_msg>Fix benches errors<commit_after>#![feature(test)]

extern crate test;
extern crate genomic_fx;
extern crate bio;

use std::collections::HashMap;

use bio::utils::{Interval, Strand};
use test::Bencher;

use genomic_fx::{ExonFeature, ExonFeatureKind, EBuilder, TBuilder, GBuilder};
use ExonFeatureKind::*;

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

    #[bench]
    fn ebuilder_no_features(b: &mut Bencher) {
        b.iter(|| {
            EBuilder::new("chrT", 100, 500)
                .strand(Strand::Forward)
                .build()
        });
    }

    #[bench]
    fn ebuiler_5_features(b: &mut Bencher) {
        b.iter(|| {
            EBuilder::new("chrT", 100, 300)
                .strand(Strand::Forward)
                .features(vec![
                    ExonFeature {
                        interval: Interval::new(100..150).unwrap(),
                        kind: UTR5,
                    },
                    ExonFeature {
                        interval: Interval::new(150..153).unwrap(),
                        kind: StartCodon { frame: Some(0) },
                    },
                    ExonFeature {
                        interval: Interval::new(150..300).unwrap(),
                        kind: CDS { frame: Some(0) },
                    },
                    ExonFeature {
                        interval: Interval::new(300..303).unwrap(),
                        kind: StopCodon { frame: Some(0) },
                    },
                    ExonFeature {
                        interval: Interval::new(300..500).unwrap(),
                        kind: UTR3,
                    },
                ])
                .build()
        });
    }

    #[bench]
    fn tbuilder_1_exon_no_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .coords(vec![(100, 10000)], None)
                .build()
        });
    }

    #[bench]
    fn tbuilder_1_exon_1_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .coords(vec![(100, 10000)], Some((200, 9500)))
                .build()
        });
    }

    #[bench]
    fn tbuilder_12_exons_no_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .coords(
                    vec![
                        (100, 300), (400, 500), (700, 1000),
                        (1100, 1300), (1400, 1500), (1700, 2000),
                        (2100, 2300), (2400, 2500), (2700, 3000),
                        (3000, 6000), (7000, 8000), (9000, 10000),
                    ], None)
                .build()
        });
    }

    #[bench]
    fn tbuilder_12_exons_with_cds(b: &mut Bencher) {
        b.iter(|| {
            TBuilder::new("chrT", 100, 10000)
                .strand(Strand::Forward)
                .id("trx01")
                .coords(
                    vec![
                        (100, 300), (400, 500), (700, 1000),
                        (1100, 1300), (1400, 1500), (1700, 2000),
                        (2100, 2300), (2400, 2500), (2700, 3000),
                        (3000, 6000), (7000, 8000), (9000, 10000),
                    ], Some((200, 9500)))
                .build()
        });
    }

    #[bench]
    fn gbuilder_no_transcripts(b: &mut Bencher) {
        b.iter(|| {
            GBuilder::new("chrT", 100, 20000)
                .strand(Strand::Forward)
                .id("gx01")
                .build()
        });
    }

    #[bench]
    fn gbuilder_3_transcripts_with_cds(b: &mut Bencher) {
        b.iter(|| {
            let mut coords = HashMap::new();
            coords.insert(
                "trx01".to_owned(),
                ((100, 10000),
                vec![
                    (100, 300), (400, 500), (700, 1000),
                    (1100, 1300), (1400, 1500), (1700, 2000),
                    (2100, 2300), (2400, 2500), (2700, 3000),
                    (3000, 6000), (7000, 8000), (9000, 10000)],
                Some((200, 9500))));
            coords.insert(
                "trx02".to_owned(),
                ((100, 10000),
                vec![
                    (100, 300), (400, 500), (700, 1000),
                    (1100, 1300), (1400, 1500), (1700, 2000),
                    (2100, 2300), (2400, 2500), (2700, 3000),
                    (3000, 6000), (7000, 8000), (9000, 10000)],
                Some((200, 9500))));
            coords.insert(
                "trx03".to_owned(),
                ((100, 10000),
                vec![
                    (100, 300), (400, 500), (700, 1000),
                    (1100, 1300), (1400, 1500), (1700, 2000),
                    (2100, 2300), (2400, 2500), (2700, 3000),
                    (3000, 6000), (7000, 8000), (9000, 10000)],
                Some((200, 9500))));
            GBuilder::new("chrT", 100, 20000)
                .strand(Strand::Forward)
                .id("gx01")
                .transcript_coords(coords)
                .build()
        });
    }
}
<|endoftext|>


<commit_before>use types;
use card::Card;
use calculator::utility;

pub fn test(cards: Vec<Card>) -> Option<types::Combination> {
  if cards.len() < 5 {
    return None;
  }

  for suit in vec![
    types::Suit::Clubs,
    types::Suit::Diamonds,
    types::Suit::Hearts,
    types::Suit::Spades,
  ] {
    if let Some(flush) = test_flush_for_suit_for_slice(suit, &cards[..]) {
      let mut result: [types::Rank; 5] = [types::Rank::Ace; 5];
      result.clone_from_slice(&flush);

      return Some(types::Combination::Flush(suit, result));
    }
  }

  return None;
}

fn test_flush_for_suit_for_slice(suit: types::Suit, cards: &[Card]) -> Option<Vec<types::Rank>> {
  let mut count = 0;
  let mut flush: Vec<Card> = vec![];
  for card in cards[..].iter() {
    if card.suit as i32 == suit as i32 {
      flush.push(*card);
      count = count + 1;
    }
  }

  utility::sort_cards(&mut flush);

  if count > 4 {
    flush.truncate(5);
    return Some(
      flush
        .iter()
        .map(|card| card.rank)
        .collect::<Vec<types::Rank>>(),
    );
  }

  None
}

#[cfg(test)]
mod tests {
  use super::*;
  #[test]
  fn none_for_empty() {
    assert_eq!(None, test(vec![]));
  }

  #[test]
  fn none_for_four_cards() {
    let cards = [
      Card {
        rank: types::Rank::Two,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Queen,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::King,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Three,
        suit: types::Suit::Spades,
      },
    ];

    assert_eq!(None, test(cards.to_vec()));
  }

  #[test]
  fn option_for_five_cards() {
    let cards = [
      Card {
        rank: types::Rank::Two,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Queen,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::King,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Three,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Ace,
        suit: types::Suit::Spades,
      },
    ];

    assert_eq!(
      Some(types::Combination::Flush(
        types::Suit::Spades,
        [
          types::Rank::Ace,
          types::Rank::King,
          types::Rank::Queen,
          types::Rank::Three,
          types::Rank::Two
        ]
      )),
      test(cards.to_vec())
    );
  }

  #[test]
  fn option_for_seven_unsorted_cards_all_spades() {
    let cards = [
      Card {
        rank: types::Rank::Two,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Queen,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::King,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Three,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Ace,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Ten,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Five,
        suit: types::Suit::Spades,
      },
    ];

    assert_eq!(
      Some(types::Combination::Flush(
        types::Suit::Spades,
        [
          types::Rank::Ace,
          types::Rank::King,
          types::Rank::Queen,
          types::Rank::Ten,
          types::Rank::Five
        ]
      )),
      test(cards.to_vec())
    );
  }

  #[test]
  fn option_for_seven_unsorted_cards_with_only_five_spades() {
    let cards = [
      Card {
        rank: types::Rank::Two,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Queen,
        suit: types::Suit::Diamonds,
      },
      Card {
        rank: types::Rank::King,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Three,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Ace,
        suit: types::Suit::Hearts,
      },
      Card {
        rank: types::Rank::Ten,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Five,
        suit: types::Suit::Spades,
      },
    ];

    assert_eq!(
      Some(types::Combination::Flush(
        types::Suit::Spades,
        [
          types::Rank::King,
          types::Rank::Ten,
          types::Rank::Five,
          types::Rank::Three,
          types::Rank::Two
        ]
      )),
      test(cards.to_vec())
    );
  }

}
<commit_msg>one more test for flush<commit_after>use types;
use card::Card;
use calculator::utility;

pub fn test(cards: Vec<Card>) -> Option<types::Combination> {
  if cards.len() < 5 {
    return None;
  }

  for suit in vec![
    types::Suit::Clubs,
    types::Suit::Diamonds,
    types::Suit::Hearts,
    types::Suit::Spades,
  ] {
    if let Some(flush) = test_flush_for_suit_for_slice(suit, &cards[..]) {
      let mut result: [types::Rank; 5] = [types::Rank::Ace; 5];
      result.clone_from_slice(&flush);

      return Some(types::Combination::Flush(suit, result));
    }
  }

  return None;
}

fn test_flush_for_suit_for_slice(suit: types::Suit, cards: &[Card]) -> Option<Vec<types::Rank>> {
  let mut count = 0;
  let mut flush: Vec<Card> = vec![];
  for card in cards[..].iter() {
    if card.suit as i32 == suit as i32 {
      flush.push(*card);
      count = count + 1;
    }
  }

  utility::sort_cards(&mut flush);

  if count > 4 {
    flush.truncate(5);
    return Some(
      flush
        .iter()
        .map(|card| card.rank)
        .collect::<Vec<types::Rank>>(),
    );
  }

  None
}

#[cfg(test)]
mod tests {
  use super::*;
  #[test]
  fn none_for_empty() {
    assert_eq!(None, test(vec![]));
  }

  #[test]
  fn none_for_four_cards() {
    let cards = [
      Card {
        rank: types::Rank::Two,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Queen,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::King,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Three,
        suit: types::Suit::Spades,
      },
    ];

    assert_eq!(None, test(cards.to_vec()));
  }

  #[test]
  fn option_for_five_cards() {
    let cards = [
      Card {
        rank: types::Rank::Two,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Queen,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::King,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Three,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Ace,
        suit: types::Suit::Spades,
      },
    ];

    assert_eq!(
      Some(types::Combination::Flush(
        types::Suit::Spades,
        [
          types::Rank::Ace,
          types::Rank::King,
          types::Rank::Queen,
          types::Rank::Three,
          types::Rank::Two
        ]
      )),
      test(cards.to_vec())
    );
  }

  #[test]
  fn option_for_seven_unsorted_cards_all_spades() {
    let cards = [
      Card {
        rank: types::Rank::Two,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Queen,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::King,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Three,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Ace,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Ten,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Five,
        suit: types::Suit::Spades,
      },
    ];

    assert_eq!(
      Some(types::Combination::Flush(
        types::Suit::Spades,
        [
          types::Rank::Ace,
          types::Rank::King,
          types::Rank::Queen,
          types::Rank::Ten,
          types::Rank::Five
        ]
      )),
      test(cards.to_vec())
    );
  }

  #[test]
  fn option_for_seven_unsorted_cards_with_only_five_spades() {
    let cards = [
      Card {
        rank: types::Rank::Two,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Queen,
        suit: types::Suit::Diamonds,
      },
      Card {
        rank: types::Rank::King,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Three,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Ace,
        suit: types::Suit::Hearts,
      },
      Card {
        rank: types::Rank::Ten,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Five,
        suit: types::Suit::Spades,
      },
    ];

    assert_eq!(
      Some(types::Combination::Flush(
        types::Suit::Spades,
        [
          types::Rank::King,
          types::Rank::Ten,
          types::Rank::Five,
          types::Rank::Three,
          types::Rank::Two
        ]
      )),
      test(cards.to_vec())
    );
  }

  #[test]
  fn none_for_seven_unsorted_cards_with_only_four_spades() {
    let cards = [
      Card {
        rank: types::Rank::Two,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Queen,
        suit: types::Suit::Diamonds,
      },
      Card {
        rank: types::Rank::King,
        suit: types::Suit::Clubs,
      },
      Card {
        rank: types::Rank::Three,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Ace,
        suit: types::Suit::Hearts,
      },
      Card {
        rank: types::Rank::Ten,
        suit: types::Suit::Spades,
      },
      Card {
        rank: types::Rank::Five,
        suit: types::Suit::Spades,
      },
    ];

    assert_eq!(None, test(cards.to_vec()));
  }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::*;
use timely::dataflow::operators::probe::Handle;

use differential_dataflow::input::Input;
use differential_dataflow::Collection;
use differential_dataflow::operators::*;
use differential_dataflow::lattice::Lattice;
use differential_dataflow::operators::iterate::Variable;

type Node = u32;
type Edge = (Node, Node);

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: u32 = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: u32 = std::env::args().nth(3).unwrap().parse().unwrap();
    let rounds: u32 = std::env::args().nth(4).unwrap().parse().unwrap();
    let inspect: bool = std::env::args().nth(5).unwrap() == "inspect";

    // define a new computational scope, in which to run BFS
    timely::execute_from_args(std::env::args().skip(6), move |worker| {

        let timer = ::std::time::Instant::now();

        // define BFS dataflow; return handles to roots and edges inputs
        let mut probe = Handle::new();
        let (mut roots, mut graph) = worker.dataflow(|scope| {

            let (root_input, roots) = scope.new_collection();
            let (edge_input, graph) = scope.new_collection();

            let mut result = bidijkstra(&graph, &roots);

            if !inspect {
                result = result.filter(|_| false);
            }

            result.map(|(_,l)| l)
                  .consolidate()
                  .inspect(|x| println!("\t{:?}", x))
                  .probe_with(&mut probe);

            (root_input, edge_input)
        });

        let seed: &[_] = &[1, 2, 3, 4];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

        roots.insert((0, 1));
        roots.close();

        println!("performing BFS on {} nodes, {} edges:", nodes, edges);

        if worker.index() == 0 {
            for _ in 0 .. edges {
                graph.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
            }
        }

        println!("loaded; elapsed: {:?}", timer.elapsed());

        graph.advance_to(1);
        graph.flush();
        worker.step_while(|| probe.less_than(graph.time()));

        println!("stable");

        for round in 0 .. rounds {
            for element in 0 .. batch {
                if worker.index() == 0 {
                    graph.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
                    graph.remove((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)));
                }
                graph.advance_to(2 + round * batch + element);
            }
            graph.flush();

            let timer = ::std::time::Instant::now();
            worker.step_while(|| probe.less_than(&graph.time()));

            if worker.index() == 0 {
                let elapsed = timer.elapsed();
                println!("{:?}:\t{}", round, elapsed.as_secs() * 1000000000 + (elapsed.subsec_nanos() as u64));
            }
        }
        println!("finished; elapsed: {:?}", timer.elapsed());
    }).unwrap();
}

// returns pairs (n, s) indicating node n can be reached from a root in s steps.
fn bidijkstra<G: Scope>(edges: &Collection<G, Edge>, goals: &Collection<G, (Node, Node)>) -> Collection<G, ((Node, Node), u32)>
where G::Timestamp: Lattice+Ord {

    edges.scope().scoped(|inner| {

        // Our plan is to start evolving distances from both sources and destinations.
        // The evolution from a source or destination should continue as long as there
        // is a corresponding destination or source that has not yet been reached.

        // forward and reverse (node, (root, dist))
        let forward = Variable::from(goals.map(|(x,_)| (x,(x,0))).enter(inner));
        let reverse = Variable::from(goals.map(|(_,y)| (y,(y,0))).enter(inner));

        let goals = goals.enter(inner);
        let edges = edges.enter(inner);

        // Let's determine which (src, dst) pairs are ready to return.
        //
        //   done(src, dst) := forward(src, med), reverse(dst, med), goal(src, dst).
        //
        // This is a cyclic join, which should scare us a bunch.
        let reached =
        forward
            .join_map_u(&reverse, |_, &(src,d1), &(dst,d2)| ((src, dst), d1 + d2))
            .group(|_key, s, t| t.push((s[0].0, 1)));
            // .inspect(|x| println!("reached: {:?}", x));

        let active =
        reached
            .semijoin(&goals)
            .negate()
            .map(|(srcdst,_)| srcdst)
            .concat(&goals)
            // .inspect(|x| println!("active: {:?}", x))
            .consolidate();

        // Let's expand out forward queries that are active.
        let forward_active = active.map(|(x,_y)| x).distinct_u();
        let forward_next =
        forward
            // .inspect(|x| println!("forward: {:?}", x))
            .map(|(med, (src, dist))| (src, (med, dist)))
            .semijoin_u(&forward_active)
            .map(|(src, (med, dist))| (med, (src, dist)))
            .join_map_u(&edges, |_med, &(src, dist), &next| (next, (src, dist+1)))
            .concat(&forward)
            .map(|(next, (src, dist))| ((next, src), dist))
            .group(|_key, s, t| t.push((s[0].0, 1)))
            .map(|((next, src), dist)| (next, (src, dist)));

        forward.set(&forward_next);

        // Let's expand out reverse queries that are active.
        let reverse_active = active.map(|(_x,y)| y).distinct_u();
        let reverse_next =
        reverse
            // .inspect(|x| println!("reverse: {:?}", x))
            .map(|(med, (rev, dist))| (rev, (med, dist)))
            .semijoin_u(&reverse_active)
            .map(|(rev, (med, dist))| (med, (rev, dist)))
            .join_map_u(&edges.map(|(x,y)| (y,x)), |_med, &(rev, dist), &next| (next, (rev, dist+1)))
            .concat(&reverse)
            .map(|(next, (rev, dist))| ((next, rev), dist))
            .group(|_key, s, t| t.push((s[0].0, 1)))
            .map(|((next,rev), dist)| (next, (rev, dist)));

        reverse.set(&reverse_next);

        reached.leave()
    })
}<commit_msg>added more measurements<commit_after>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::*;
use timely::dataflow::operators::probe::Handle;

use differential_dataflow::input::Input;
use differential_dataflow::Collection;
use differential_dataflow::operators::*;
use differential_dataflow::lattice::Lattice;
use differential_dataflow::operators::iterate::Variable;

type Node = u32;
type Edge = (Node, Node);

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: u32 = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: u32 = std::env::args().nth(3).unwrap().parse().unwrap();
    let rounds: u32 = std::env::args().nth(4).unwrap().parse().unwrap();
    let inspect: bool = std::env::args().nth(5).unwrap() == "inspect";

    // define a new computational scope, in which to run BFS
    timely::execute_from_args(std::env::args().skip(6), move |worker| {

        let timer = ::std::time::Instant::now();

        // define BFS dataflow; return handles to roots and edges inputs
        let mut probe = Handle::new();
        let (mut roots, mut graph) = worker.dataflow(|scope| {

            let (root_input, roots) = scope.new_collection();
            let (edge_input, graph) = scope.new_collection();

            let mut result = bidijkstra(&graph, &roots);

            if !inspect {
                result = result.filter(|_| false);
            }

            result.map(|(_,l)| l)
                  .consolidate()
                  .inspect(|x| println!("\t{:?}", x))
                  .probe_with(&mut probe);

            (root_input, edge_input)
        });

        let seed: &[_] = &[1, 2, 3, 4];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge deletions

        println!("performing BFS on {} nodes, {} edges:", nodes, edges);

        if worker.index() == 0 {
            for _ in 0 .. edges {
                graph.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
            }
        }
        println!("loaded; elapsed: {:?}", timer.elapsed());

        roots.advance_to(1); roots.flush();
        graph.advance_to(1); graph.flush();
        worker.step_while(|| probe.less_than(graph.time()));
        println!("stable; elapsed: {:?}", timer.elapsed());

        roots.insert((0, 1));
        roots.close();
        graph.advance_to(2); graph.flush();
        worker.step_while(|| probe.less_than(graph.time()));
        println!("queried; elapsed: {:?}", timer.elapsed());

        for round in 0 .. rounds {
            for element in 0 .. batch {
                if worker.index() == 0 {
                    graph.insert((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)));
                    graph.remove((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)));
                }
                graph.advance_to(3 + round * batch + element);
            }
            graph.flush();

            let timer = ::std::time::Instant::now();
            worker.step_while(|| probe.less_than(&graph.time()));

            if worker.index() == 0 {
                let elapsed = timer.elapsed();
                println!("{:?}:\t{}", round, elapsed.as_secs() * 1000000000 + (elapsed.subsec_nanos() as u64));
            }
        }
        println!("finished; elapsed: {:?}", timer.elapsed());
    }).unwrap();
}

// returns pairs (n, s) indicating node n can be reached from a root in s steps.
fn bidijkstra<G: Scope>(edges: &Collection<G, Edge>, goals: &Collection<G, (Node, Node)>) -> Collection<G, ((Node, Node), u32)>
where G::Timestamp: Lattice+Ord {

    edges.scope().scoped(|inner| {

        // Our plan is to start evolving distances from both sources and destinations.
        // The evolution from a source or destination should continue as long as there
        // is a corresponding destination or source that has not yet been reached.

        // forward and reverse (node, (root, dist))
        let forward = Variable::from(goals.map(|(x,_)| (x,(x,0))).enter(inner));
        let reverse = Variable::from(goals.map(|(_,y)| (y,(y,0))).enter(inner));

        let goals = goals.enter(inner);
        let edges = edges.enter(inner);

        // Let's determine which (src, dst) pairs are ready to return.
        //
        //   done(src, dst) := forward(src, med), reverse(dst, med), goal(src, dst).
        //
        // This is a cyclic join, which should scare us a bunch.
        let reached =
        forward
            .join_map_u(&reverse, |_, &(src,d1), &(dst,d2)| ((src, dst), d1 + d2))
            .group(|_key, s, t| t.push((s[0].0, 1)));
            // .inspect(|x| println!("reached: {:?}", x));

        let active =
        reached
            .semijoin(&goals)
            .negate()
            .map(|(srcdst,_)| srcdst)
            .concat(&goals)
            // .inspect(|x| println!("active: {:?}", x))
            .consolidate();

        // Let's expand out forward queries that are active.
        let forward_active = active.map(|(x,_y)| x).distinct_u();
        let forward_next =
        forward
            // .inspect(|x| println!("forward: {:?}", x))
            .map(|(med, (src, dist))| (src, (med, dist)))
            .semijoin_u(&forward_active)
            .map(|(src, (med, dist))| (med, (src, dist)))
            .join_map_u(&edges, |_med, &(src, dist), &next| (next, (src, dist+1)))
            .concat(&forward)
            .map(|(next, (src, dist))| ((next, src), dist))
            .group(|_key, s, t| t.push((s[0].0, 1)))
            .map(|((next, src), dist)| (next, (src, dist)));

        forward.set(&forward_next);

        // Let's expand out reverse queries that are active.
        let reverse_active = active.map(|(_x,y)| y).distinct_u();
        let reverse_next =
        reverse
            // .inspect(|x| println!("reverse: {:?}", x))
            .map(|(med, (rev, dist))| (rev, (med, dist)))
            .semijoin_u(&reverse_active)
            .map(|(rev, (med, dist))| (med, (rev, dist)))
            .join_map_u(&edges.map(|(x,y)| (y,x)), |_med, &(rev, dist), &next| (next, (rev, dist+1)))
            .concat(&reverse)
            .map(|(next, (rev, dist))| ((next, rev), dist))
            .group(|_key, s, t| t.push((s[0].0, 1)))
            .map(|((next,rev), dist)| (next, (rev, dist)));

        reverse.set(&reverse_next);

        reached.leave()
    })
}<|endoftext|>


<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cfg_if::cfg_if! {
    if #[cfg(unix)] {
        use std::env;
        use std::ffi::OsStr;
        use std::fs;
        use std::path::{Path, PathBuf};
        use std::process::Command;

        // Performs a recursive search for a file with name under path and returns the full path if such a
        // file is found.
        fn scan_path<P: AsRef<Path>, O: AsRef<OsStr>>(path: P, name: O) -> Option<PathBuf> {
            for entry in (fs::read_dir(path).ok()?).flatten() {
                let file_type = match entry.file_type() {
                    Ok(t) => t,
                    Err(_) => continue,
                };

                if file_type.is_file() && entry.file_name() == name.as_ref() {
                    return Some(entry.path());
                } else if file_type.is_dir() {
                    if let Some(found) = scan_path(entry.path(), name.as_ref()) {
                        return Some(found);
                    }
                }
            }
            None
        }

        // Searches for the given protocol in both the system wide and bundles protocols path.
        fn find_protocol(name: &str) -> PathBuf {
            let protocol_file_name = PathBuf::from(format!("{}.xml", name));
            // Prioritize the systems wayland protocols before using the bundled ones.
            if let Ok(protocols_path) = pkg_config::get_variable("wayland-protocols", "pkgdatadir") {
                if let Some(found) = scan_path(protocols_path, &protocol_file_name) {
                    return found;
                }
            }
            let protocols_path = format!("/usr/share/wayland-protocols/stable/{}", name);
            if let Some(found) = scan_path(protocols_path, &protocol_file_name) {
                return found;
            }
            // Use bundled protocols as a fallback.
            let protocol_path = Path::new("protocol").join(protocol_file_name);
            assert!(
                protocol_path.is_file(),
                "unable to locate wayland protocol specification for `{}`",
                name
            );
            protocol_path
        }

        fn compile_protocol<P: AsRef<Path>>(name: &str, out: P) -> PathBuf {
            let in_protocol = find_protocol(name);
            println!("cargo:rerun-if-changed={}", in_protocol.display());
            let out_code = out.as_ref().join(format!("{}.c", name));
            let out_header = out.as_ref().join(format!("{}.h", name));
            eprintln!("building protocol: {}", name);
            Command::new("wayland-scanner")
                .arg("code")
                .arg(&in_protocol)
                .arg(&out_code)
                .output()
                .expect("wayland-scanner code failed");
            Command::new("wayland-scanner")
                .arg("client-header")
                .arg(&in_protocol)
                .arg(&out_header)
                .output()
                .expect("wayland-scanner client-header failed");
            out_code
        }

        fn main() {
            // Skip installing dependencies when generating documents.
            if std::env::var("CARGO_DOC").is_ok() {
                return;
            }

            println!("cargo:rerun-if-env-changed=WAYLAND_PROTOCOLS_PATH");
            let out_dir = env::var("OUT_DIR").unwrap();

            let mut build = cc::Build::new();
            build.warnings(true);
            build.warnings_into_errors(true);
            build.include(&out_dir);
            build.flag("-std=gnu11");
            build.file("src/display_wl.c");
            println!("cargo:rerun-if-changed=src/display_wl.c");

            for protocol in &[
                "aura-shell",
                "linux-dmabuf-unstable-v1",
                "xdg-shell",
                "viewporter",
                "virtio-gpu-metadata-v1",
            ] {
                build.file(compile_protocol(protocol, &out_dir));
            }
            build.compile("display_wl");

            println!("cargo:rustc-link-lib=dylib=wayland-client");
        }

    } else if #[cfg(windows)] {
        fn main() {}
    }
}
<commit_msg>gpu_display: rework build.rs for cross compilation<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::env;
use std::ffi::OsStr;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;

// Performs a recursive search for a file with name under path and returns the full path if such a
// file is found.
fn scan_path<P: AsRef<Path>, O: AsRef<OsStr>>(path: P, name: O) -> Option<PathBuf> {
    for entry in (fs::read_dir(path).ok()?).flatten() {
        let file_type = match entry.file_type() {
            Ok(t) => t,
            Err(_) => continue,
        };

        if file_type.is_file() && entry.file_name() == name.as_ref() {
            return Some(entry.path());
        } else if file_type.is_dir() {
            if let Some(found) = scan_path(entry.path(), name.as_ref()) {
                return Some(found);
            }
        }
    }
    None
}

// Searches for the given protocol in both the system wide and bundles protocols path.
fn find_protocol(name: &str) -> PathBuf {
    let protocol_file_name = PathBuf::from(format!("{}.xml", name));
    // Prioritize the systems wayland protocols before using the bundled ones.
    if let Ok(protocols_path) = pkg_config::get_variable("wayland-protocols", "pkgdatadir") {
        if let Some(found) = scan_path(protocols_path, &protocol_file_name) {
            return found;
        }
    }
    let protocols_path = format!("/usr/share/wayland-protocols/stable/{}", name);
    if let Some(found) = scan_path(protocols_path, &protocol_file_name) {
        return found;
    }
    // Use bundled protocols as a fallback.
    let protocol_path = Path::new("protocol").join(protocol_file_name);
    assert!(
        protocol_path.is_file(),
        "unable to locate wayland protocol specification for `{}`",
        name
    );
    protocol_path
}

fn compile_protocol<P: AsRef<Path>>(name: &str, out: P) -> PathBuf {
    let in_protocol = find_protocol(name);
    println!("cargo:rerun-if-changed={}", in_protocol.display());
    let out_code = out.as_ref().join(format!("{}.c", name));
    let out_header = out.as_ref().join(format!("{}.h", name));
    eprintln!("building protocol: {}", name);
    Command::new("wayland-scanner")
        .arg("code")
        .arg(&in_protocol)
        .arg(&out_code)
        .output()
        .expect("wayland-scanner code failed");
    Command::new("wayland-scanner")
        .arg("client-header")
        .arg(&in_protocol)
        .arg(&out_header)
        .output()
        .expect("wayland-scanner client-header failed");
    out_code
}

fn main() {
    // Do nothing on Windows.
    if std::env::var("CARGO_CFG_WINDOWS").is_ok() {
        return;
    }

    // Skip installing dependencies when generating documents.
    if std::env::var("CARGO_DOC").is_ok() {
        return;
    }

    println!("cargo:rerun-if-env-changed=WAYLAND_PROTOCOLS_PATH");
    let out_dir = env::var("OUT_DIR").unwrap();

    let mut build = cc::Build::new();
    build.warnings(true);
    build.warnings_into_errors(true);
    build.include(&out_dir);
    build.flag("-std=gnu11");
    build.file("src/display_wl.c");
    println!("cargo:rerun-if-changed=src/display_wl.c");

    for protocol in &[
        "aura-shell",
        "linux-dmabuf-unstable-v1",
        "xdg-shell",
        "viewporter",
        "virtio-gpu-metadata-v1",
    ] {
        build.file(compile_protocol(protocol, &out_dir));
    }
    build.compile("display_wl");

    println!("cargo:rustc-link-lib=dylib=wayland-client");
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

///
/// Example cUrl request:
/// curl -X PUT -d '[[[{"id":"setter:talk@link.mozilla.org"}], {"String": "hello world"}]]' http://localhost:3000/api/v1/channels/set
///

use foxbox_taxonomy::adapter::*;
use foxbox_taxonomy::manager::AdapterManager;
use foxbox_taxonomy::api::{ Error, InternalError, User };
use foxbox_taxonomy::services::{ AdapterId, Channel, ChannelKind, Id, Service, ServiceId };
use foxbox_taxonomy::values::{ Type, Value };
use std::collections::{ HashMap, HashSet };
use std::sync::Arc;
use transformable_channels::mpsc::*;

pub mod engine;
pub use self::engine::TtsEngine;

// eSpeak is the only engine supported for now.
mod espeak;
use self::espeak::EspeakEngine;

static ADAPTER_ID: &'static str = "espeak_adapter@link.mozilla.org";
static ADAPTER_NAME: &'static str = "eSpeak adapter";
static ADAPTER_VENDOR: &'static str = "team@link.mozilla.org";
static ADAPTER_VERSION: [u32;4] = [0, 0, 0, 0];

pub struct TtsAdapter<T> {
    talk_setter_id: Id<Channel>,
    engine: T
}

impl<T: TtsEngine> Adapter for TtsAdapter<T> {
    fn id(&self) -> Id<AdapterId> {
        adapter_id!(ADAPTER_ID)
    }

    fn name(&self) -> &str {
        ADAPTER_NAME
    }

    fn vendor(&self) -> &str {
        ADAPTER_VENDOR
    }

    fn version(&self) -> &[u32;4] {
        &ADAPTER_VERSION
    }

    fn fetch_values(&self, mut set: Vec<Id<Channel>>, _: User) -> ResultMap<Id<Channel>, Option<Value>, Error> {
        set.drain(..).map(|id| {
            (id.clone(), Err(Error::InternalError(InternalError::NoSuchChannel(id))))
        }).collect()
    }

    fn send_values(&self, mut values: HashMap<Id<Channel>, Value>, _: User) -> ResultMap<Id<Channel>, (), Error> {
        use core::ops::Deref;

        values.drain().map(|(id, value)| {
            if id == self.talk_setter_id {
                if let Value::String(text) = value {
                    self.engine.say(text.deref());
                    return (id, Ok(()));
                }
            }
            (id.clone(), Err(Error::InternalError(InternalError::NoSuchChannel(id))))
        }).collect()
    }

    fn register_watch(&self, mut watch: Vec<WatchTarget>) -> WatchResult
    {
        watch.drain(..).map(|(id, _, _)| {
            (id.clone(), Err(Error::GetterDoesNotSupportWatching(id)))
        }).collect()
    }
}

pub fn init(adapt: &Arc<AdapterManager>) -> Result<(), Error> {
    let engine = EspeakEngine { };
    if !engine.init() {
        warn!("eSpeak initialization failed!");
        return Err(Error::InternalError(InternalError::GenericError("eSpeak initialization failed!".to_owned())));
    }

    let talk_setter_id = Id::new("setter:talk@link.mozilla.org");
    try!(adapt.add_adapter(Arc::new(TtsAdapter {
        talk_setter_id: talk_setter_id.clone(),
        engine: engine
    })));
    let service_id = service_id!("espeak@link.mozilla.org");
    let adapter_id = adapter_id!(ADAPTER_ID);
    try!(adapt.add_service(Service::empty(&service_id, &adapter_id)));
    try!(adapt.add_channel(Channel {
        kind: ChannelKind::Extension {
            vendor: Id::new(ADAPTER_VENDOR),
            adapter: Id::new(ADAPTER_NAME),
            kind: Id::new("Sentence"),
            typ: Type::String,
        },
        supports_send: true,
        .. Channel::empty(&talk_setter_id, &service_id, &adapter_id)
    }));
    Ok(())
}
<commit_msg>Remove unused import (#493)<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

///
/// Example cUrl request:
/// curl -X PUT -d '[[[{"id":"setter:talk@link.mozilla.org"}], {"String": "hello world"}]]' http://localhost:3000/api/v1/channels/set
///

use foxbox_taxonomy::adapter::*;
use foxbox_taxonomy::manager::AdapterManager;
use foxbox_taxonomy::api::{ Error, InternalError, User };
use foxbox_taxonomy::services::{ AdapterId, Channel, ChannelKind, Id, Service, ServiceId };
use foxbox_taxonomy::values::{ Type, Value };
use std::collections::HashMap;
use std::sync::Arc;
use transformable_channels::mpsc::*;

pub mod engine;
pub use self::engine::TtsEngine;

// eSpeak is the only engine supported for now.
mod espeak;
use self::espeak::EspeakEngine;

static ADAPTER_ID: &'static str = "espeak_adapter@link.mozilla.org";
static ADAPTER_NAME: &'static str = "eSpeak adapter";
static ADAPTER_VENDOR: &'static str = "team@link.mozilla.org";
static ADAPTER_VERSION: [u32;4] = [0, 0, 0, 0];

pub struct TtsAdapter<T> {
    talk_setter_id: Id<Channel>,
    engine: T
}

impl<T: TtsEngine> Adapter for TtsAdapter<T> {
    fn id(&self) -> Id<AdapterId> {
        adapter_id!(ADAPTER_ID)
    }

    fn name(&self) -> &str {
        ADAPTER_NAME
    }

    fn vendor(&self) -> &str {
        ADAPTER_VENDOR
    }

    fn version(&self) -> &[u32;4] {
        &ADAPTER_VERSION
    }

    fn fetch_values(&self, mut set: Vec<Id<Channel>>, _: User) -> ResultMap<Id<Channel>, Option<Value>, Error> {
        set.drain(..).map(|id| {
            (id.clone(), Err(Error::InternalError(InternalError::NoSuchChannel(id))))
        }).collect()
    }

    fn send_values(&self, mut values: HashMap<Id<Channel>, Value>, _: User) -> ResultMap<Id<Channel>, (), Error> {
        use core::ops::Deref;

        values.drain().map(|(id, value)| {
            if id == self.talk_setter_id {
                if let Value::String(text) = value {
                    self.engine.say(text.deref());
                    return (id, Ok(()));
                }
            }
            (id.clone(), Err(Error::InternalError(InternalError::NoSuchChannel(id))))
        }).collect()
    }

    fn register_watch(&self, mut watch: Vec<WatchTarget>) -> WatchResult
    {
        watch.drain(..).map(|(id, _, _)| {
            (id.clone(), Err(Error::GetterDoesNotSupportWatching(id)))
        }).collect()
    }
}

pub fn init(adapt: &Arc<AdapterManager>) -> Result<(), Error> {
    let engine = EspeakEngine { };
    if !engine.init() {
        warn!("eSpeak initialization failed!");
        return Err(Error::InternalError(InternalError::GenericError("eSpeak initialization failed!".to_owned())));
    }

    let talk_setter_id = Id::new("setter:talk@link.mozilla.org");
    try!(adapt.add_adapter(Arc::new(TtsAdapter {
        talk_setter_id: talk_setter_id.clone(),
        engine: engine
    })));
    let service_id = service_id!("espeak@link.mozilla.org");
    let adapter_id = adapter_id!(ADAPTER_ID);
    try!(adapt.add_service(Service::empty(&service_id, &adapter_id)));
    try!(adapt.add_channel(Channel {
        kind: ChannelKind::Extension {
            vendor: Id::new(ADAPTER_VENDOR),
            adapter: Id::new(ADAPTER_NAME),
            kind: Id::new("Sentence"),
            typ: Type::String,
        },
        supports_send: true,
        .. Channel::empty(&talk_setter_id, &service_id, &adapter_id)
    }));
    Ok(())
}
<|endoftext|>