<commit_before>extern crate lp_modeler;

use std::collections::HashMap;

use lp_modeler::solvers::{CbcSolver, SolverTrait, Solution, NativeCbcSolver};
use lp_modeler::dsl::*;
use lp_modeler::format::lp_format::LpFileFormat;

#[test]
fn test_readme_example_1() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    let mut problem = LpProblem::new("One Problem", LpObjective::Maximize);
    problem += 10.0 * a + 20.0 * b;

    problem += (500 * a + 1200 * b + 1500 * c).le(10000);
    problem += (a).le(b);

    let solver = CbcSolver::new();

    match solver.run(&problem) {
        Ok( solution ) => {
            println!("Status {:?}", solution.status);
            for (name, value) in solution.results.iter() {
                println!("value of {} = {}", name, value);
            }
        }
        Err(msg) => println!("{}", msg),
    }

    let output1 = "\\ One Problem
Maximize
  obj: 10 a + 20 b
Subject To
  c1: 500 a + 1200 b + 1500 c <= 10000
  c2: a - b <= 0
"
        .to_string();
    let output2 = problem.to_lp_file_format();
    let output2 = output2.split("Generals").collect::<Vec<&str>>();
    let output2 = output2[0];
    assert_eq!(output1, output2);
}

#[test]
fn test_full_example() {
    let ref a = LpInteger::new("a").lower_bound(1.0);
    let ref b = LpInteger::new("b").upper_bound(10.0);
    let ref c = LpInteger::new("c").lower_bound(2.0).upper_bound(8.5);
    let ref d = LpBinary::new("d");
    let ref e = LpContinuous::new("e");

    let mut problem = LpProblem::new("One Problem", LpObjective::Maximize);
    problem += a + b + c + d + e;

    problem += (a + b + c + d + e).le(100.0);

    let solver = CbcSolver::new();

    match solver.run(&problem) {
        Ok( solution ) => {
            println!("Status {:?}", solution.status);
            for (name, value) in solution.results.iter() {
                println!("value of {} = {}", name, value);
            }
        }
        Err(msg) => println!("{}", msg),
    }

    let output1 = problem.to_lp_file_format();
    for expr in vec!("e free", "1 <= a", "2 <= c <= 8.5", "b <= 10") {
        assert!(output1.contains(expr), format!("{} is not present",expr));
    }
}

#[test]
fn test_readme_example_2() {
    // Problem Data
    let men = vec!["A", "B", "C"];
    let women = vec!["D", "E", "F"];
    let compat_scores : HashMap<(&str,&str),f32> = vec![
        (("A", "D"), 50.0),
        (("A", "E"), 75.0),
        (("A", "F"), 75.0),
        (("B", "D"), 60.0),
        (("B", "E"), 95.0),
        (("B", "F"), 80.0),
        (("C", "D"), 60.0),
        (("C", "E"), 70.0),
        (("C", "F"), 80.0),
    ].into_iter().collect();

    // Define Problem
    let mut problem = LpProblem::new("Matchmaking", LpObjective::Maximize);

    // Define Variables
    let mut vars = HashMap::new();
    for m in &men {
        for w in &women {
            vars.insert((m, w), LpBinary::new(&format!("{}_{}", m, w)));
        }
    }

    // Define Objective Function
    let mut obj_vec: Vec<LpExpression> = Vec::new();
    for (&(&m, &w), var) in &vars {
        let obj_coef = compat_scores.get(&(m, w)).unwrap();
        obj_vec.push(*obj_coef * var);
    }
    problem += lp_sum(&obj_vec);

    // Define Constraints
    // Constraint 1: Each man must be assigned to exactly one woman
    for m in &men {
        let mut constr_vec = Vec::new();

        for w in &women {
            constr_vec.push(1.0 * vars.get(&(m, w)).unwrap());
        }

        problem += lp_sum(&constr_vec).equal(1);
    }

    // Constraint 2: Each woman must be assigned to exactly one man
    for w in &women {
        let mut constr_vec = Vec::new();

        for m in &men {
            constr_vec.push(1.0 * vars.get(&(m, w)).unwrap());
        }

        problem += lp_sum(&constr_vec).equal(1);
    }

    // Optionally write to file
    // let result = problem.write_lp("problem.lp");
    // match result{
    //     Ok(_) => println!("Written to file"),
    //     Err(msg) => println!("{}", msg)
    // }

    // Run Solver
    let solver = CbcSolver::new();
    let result = solver.run(&problem);

    // Terminate if error, or assign status & variable values
    assert!(result.is_ok(), result.unwrap_err());
    let Solution { status: solver_status, results: var_values, related_problem: _ } = result.unwrap();

    // Compute final objective function value
    let mut obj_value = 0f32;
    for (&(&m, &w), var) in &vars {
        let obj_coef = compat_scores.get(&(m, w)).unwrap();
        let var_value = var_values.get(&var.name).unwrap();

        obj_value += obj_coef * var_value;
    }

    // Print output
    println!("Status: {:?}", solver_status);
    println!("Objective Value: {}", obj_value);
    // println!("{:?}", var_values);
    for (var_name, var_value) in &var_values {
        let int_var_value = *var_value as u32;
        if int_var_value == 1 {
            println!("{} = {}", var_name, int_var_value);
        }
    }

    assert_eq!(solver_status, lp_modeler::solvers::Status::Optimal);
    assert_eq!(obj_value, 230f32);
    assert_eq!(*var_values.get("A_F").unwrap(), 1f32);
    assert_eq!(*var_values.get("B_E").unwrap(), 1f32);
    assert_eq!(*var_values.get("C_D").unwrap(), 1f32);
}

#[test]
// as in https://github.com/KardinalAI/coin_cbc/blob/master/examples/knapsack.rs
//
// Maximize  5a + 3b + 2c + 7d + 4e
// s.t.      2a + 8b + 4c + 2d + 5e <= 10
fn cbc_native_optimal() {
    let mut problem = LpProblem::new("Knapsack", LpObjective::Maximize);
    let objective: HashMap<&str, f32> =
        vec![("a", 5.0), ("b", 3.0), ("c", 2.0), ("d", 7.0), ("e", 4.0)]
            .into_iter()
            .collect();
    let x: HashMap<&str, LpBinary> = objective
        .iter()
        .map(|(name, _)| (*name, LpBinary::new(name)))
        .collect();
        problem +=
        (2.0 * &x["a"] + 8.0 * &x["b"] + 4.0 * &x["c"] + 2. * &x["d"] + 5. * &x["e"]).le(10.);
    problem += 5.0 * &x["a"] + 3.0 * &x["b"] + 2.0 * &x["c"] + 7. * &x["d"] + 4. * &x["e"];

    let solver = NativeCbcSolver::new();

    match solver.run(&problem) {
        Ok(sol) => {
            println!("Status {:?}", sol.status);
            println!("{:?}", sol.results);
            assert_eq!(
                16f32,
                x.iter()
                    .map(|(name, var)| match sol.results.get(&var.name) {
                        Some(s) => {
                            println!("{:?}*{}", s, objective.get(name).unwrap());
                            s * objective.get(name).unwrap()
                        }
                        _ => 0.,
                    })
                    .sum()
            );
        }
        Err(msg) => panic!("Native Cbc Solver panicked at run: {}", msg),
    }
}
<commit_msg>Fix tests<commit_after>extern crate lp_modeler;

use std::collections::HashMap;

use lp_modeler::solvers::{CbcSolver, SolverTrait, Solution, NativeCbcSolver};
use lp_modeler::dsl::*;
use lp_modeler::format::lp_format::LpFileFormat;

#[test]
fn test_readme_example_1() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    let mut problem = LpProblem::new("One Problem", LpObjective::Maximize);
    problem += 10.0 * a + 20.0 * b;

    problem += (500 * a + 1200 * b + 1500 * c).le(10000);
    problem += (a).le(b);

    let solver = CbcSolver::new();

    match solver.run(&problem) {
        Ok( solution ) => {
            println!("Status {:?}", solution.status);
            for (name, value) in solution.results.iter() {
                println!("value of {} = {}", name, value);
            }
        }
        Err(msg) => println!("{}", msg),
    }

    let output1 = "\\ One Problem

Maximize
  obj: 10 a + 20 b

Subject To
  c1: 500 a + 1200 b + 1500 c <= 10000
  c2: a - b <= 0

"
        .to_string();
    let output2 = problem.to_lp_file_format();
    let output2 = output2.split("Generals").collect::<Vec<&str>>();
    let output2 = output2[0];
    assert_eq!(output1, output2);
}

#[test]
fn test_full_example() {
    let ref a = LpInteger::new("a").lower_bound(1.0);
    let ref b = LpInteger::new("b").upper_bound(10.0);
    let ref c = LpInteger::new("c").lower_bound(2.0).upper_bound(8.5);
    let ref d = LpBinary::new("d");
    let ref e = LpContinuous::new("e");

    let mut problem = LpProblem::new("One Problem", LpObjective::Maximize);
    problem += a + b + c + d + e;

    problem += (a + b + c + d + e).le(100.0);

    let solver = CbcSolver::new();

    match solver.run(&problem) {
        Ok( solution ) => {
            println!("Status {:?}", solution.status);
            for (name, value) in solution.results.iter() {
                println!("value of {} = {}", name, value);
            }
        }
        Err(msg) => println!("{}", msg),
    }

    let output1 = problem.to_lp_file_format();
    for expr in vec!("e free", "1 <= a", "2 <= c <= 8.5", "b <= 10") {
        assert!(output1.contains(expr), format!("{} is not present",expr));
    }
}

#[test]
fn test_readme_example_2() {
    // Problem Data
    let men = vec!["A", "B", "C"];
    let women = vec!["D", "E", "F"];
    let compat_scores : HashMap<(&str,&str),f32> = vec![
        (("A", "D"), 50.0),
        (("A", "E"), 75.0),
        (("A", "F"), 75.0),
        (("B", "D"), 60.0),
        (("B", "E"), 95.0),
        (("B", "F"), 80.0),
        (("C", "D"), 60.0),
        (("C", "E"), 70.0),
        (("C", "F"), 80.0),
    ].into_iter().collect();

    // Define Problem
    let mut problem = LpProblem::new("Matchmaking", LpObjective::Maximize);

    // Define Variables
    let mut vars = HashMap::new();
    for m in &men {
        for w in &women {
            vars.insert((m, w), LpBinary::new(&format!("{}_{}", m, w)));
        }
    }

    // Define Objective Function
    let mut obj_vec: Vec<LpExpression> = Vec::new();
    for (&(&m, &w), var) in &vars {
        let obj_coef = compat_scores.get(&(m, w)).unwrap();
        obj_vec.push(*obj_coef * var);
    }
    problem += lp_sum(&obj_vec);

    // Define Constraints
    // Constraint 1: Each man must be assigned to exactly one woman
    for m in &men {
        let mut constr_vec = Vec::new();

        for w in &women {
            constr_vec.push(1.0 * vars.get(&(m, w)).unwrap());
        }

        problem += lp_sum(&constr_vec).equal(1);
    }

    // Constraint 2: Each woman must be assigned to exactly one man
    for w in &women {
        let mut constr_vec = Vec::new();

        for m in &men {
            constr_vec.push(1.0 * vars.get(&(m, w)).unwrap());
        }

        problem += lp_sum(&constr_vec).equal(1);
    }

    // Optionally write to file
    // let result = problem.write_lp("problem.lp");
    // match result{
    //     Ok(_) => println!("Written to file"),
    //     Err(msg) => println!("{}", msg)
    // }

    // Run Solver
    let solver = CbcSolver::new();
    let result = solver.run(&problem);

    // Terminate if error, or assign status & variable values
    assert!(result.is_ok(), result.unwrap_err());
    let Solution { status: solver_status, results: var_values, related_problem: _ } = result.unwrap();

    // Compute final objective function value
    let mut obj_value = 0f32;
    for (&(&m, &w), var) in &vars {
        let obj_coef = compat_scores.get(&(m, w)).unwrap();
        let var_value = var_values.get(&var.name).unwrap();

        obj_value += obj_coef * var_value;
    }

    // Print output
    println!("Status: {:?}", solver_status);
    println!("Objective Value: {}", obj_value);
    // println!("{:?}", var_values);
    for (var_name, var_value) in &var_values {
        let int_var_value = *var_value as u32;
        if int_var_value == 1 {
            println!("{} = {}", var_name, int_var_value);
        }
    }

    assert_eq!(solver_status, lp_modeler::solvers::Status::Optimal);
    assert_eq!(obj_value, 230f32);
    assert_eq!(*var_values.get("A_F").unwrap(), 1f32);
    assert_eq!(*var_values.get("B_E").unwrap(), 1f32);
    assert_eq!(*var_values.get("C_D").unwrap(), 1f32);
}

#[test]
// as in https://github.com/KardinalAI/coin_cbc/blob/master/examples/knapsack.rs
//
// Maximize  5a + 3b + 2c + 7d + 4e
// s.t.      2a + 8b + 4c + 2d + 5e <= 10
fn cbc_native_optimal() {
    let mut problem = LpProblem::new("Knapsack", LpObjective::Maximize);
    let objective: HashMap<&str, f32> =
        vec![("a", 5.0), ("b", 3.0), ("c", 2.0), ("d", 7.0), ("e", 4.0)]
            .into_iter()
            .collect();
    let x: HashMap<&str, LpBinary> = objective
        .iter()
        .map(|(name, _)| (*name, LpBinary::new(name)))
        .collect();
        problem +=
        (2.0 * &x["a"] + 8.0 * &x["b"] + 4.0 * &x["c"] + 2. * &x["d"] + 5. * &x["e"]).le(10.);
    problem += 5.0 * &x["a"] + 3.0 * &x["b"] + 2.0 * &x["c"] + 7. * &x["d"] + 4. * &x["e"];

    let solver = NativeCbcSolver::new();

    match solver.run(&problem) {
        Ok(sol) => {
            println!("Status {:?}", sol.status);
            println!("{:?}", sol.results);
            assert_eq!(
                16f32,
                x.iter()
                    .map(|(name, var)| match sol.results.get(&var.name) {
                        Some(s) => {
                            println!("{:?}*{}", s, objective.get(name).unwrap());
                            s * objective.get(name).unwrap()
                        }
                        _ => 0.,
                    })
                    .sum()
            );
        }
        Err(msg) => panic!("Native Cbc Solver panicked at run: {}", msg),
    }
}
<|endoftext|>


<commit_before>//! This crate serves as a parent for library crates in the DICOM-rs project.
//!
//! For an idiomatic API to reading and writing DICOM data, please see
//! the [`object`](crate::object) module.
pub use dicom_core as core;
pub use dicom_dictionary_std as dictionary_std;
pub use dicom_encoding as encoding;
pub use dicom_object as object;
pub use dicom_parser as parser;
pub use dicom_transfer_syntax_registry as transfer_syntax;
<commit_msg>Update lib.rs<commit_after>//! This crate serves as a parent for library crates in the DICOM-rs project.
//!
//! For an idiomatic API to reading and writing DICOM data, please see
//! the [`object`](crate::object) module.
pub use dicom_core as core;
pub use dicom_dictionary_std as dictionary_std;
pub use dicom_encoding as encoding;
pub use dicom_object as object;
pub use dicom_parser as parser;
pub use dicom_transfer_syntax_registry as transfer_syntax;

// re-export dicom_value macro
#[macro_export]
pub use dicom_core::dicom_value;
<|endoftext|>


<commit_before>use app::App;
use texture::Texture;
use transform::Transform;
use component::Component;
use component::Message;
use std::collections::LinkedList;
use std::mem;
use physics::nphysics2d::object::{RigidBody, RigidBodyHandle};
use physics::nphysics2d::math::Matrix;
use physics::nalgebra::{Rotation2, Vector2, Vector1};

pub struct GameObject {
    pub transform: Transform,
    pub texture: Texture,
    body: Option<RigidBodyHandle<f64>>,
    // When searching for a component associated with a GameObject you will need to search both of
    // these vectors. At any given time either one of them could contain the Component you are
    // searching for. As messages are distributed to components they are migrated from
    // components to messaged_components and once the distribution of a message is complete
    // the two vectors are swapped.
    components: LinkedList<Box<Component>>, // These have not had a message sent (yet).
    messaged_components: LinkedList<Box<Component>>, // These have had a message sent.
}

impl GameObject {
    pub fn new(app: &mut App) -> GameObject {
        GameObject {
            transform: Transform::new(),
            components: LinkedList::new(),
            messaged_components: LinkedList::new(),
            texture: Texture::empty(app),
            body: None,
        }
    }

    pub fn update(&mut self, app: &mut App, delta_time: f64) {
        let mut pop_result = self.components.pop_front();
        while let Some(mut component) = pop_result {
            component.receive_message(app, self, &Message::Update { delta_time: delta_time });
            self.messaged_components.push_back(component);
            pop_result = self.components.pop_front();
        }
        assert_eq!(self.components.len(), 0);
        mem::swap(&mut self.components, &mut self.messaged_components);
    }

    pub fn add_component(&mut self, component: Box<Component>) {
        self.components.push_front(component);
    }

    pub fn set_rigid_body(&mut self, app: &mut App, rigid_body: RigidBody<f64>) {
        self.body = Some(app.world.add_rigid_body(rigid_body));
    }
}

pub fn copy_from_physics(game_object: &mut GameObject) {
    if let &Some(ref body_box) = &game_object.body {
        let body_borrow = body_box.borrow();
        *game_object.transform.mut_x() = body_borrow.position().translation.x;
        *game_object.transform.mut_y() = body_borrow.position().translation.y;
        let matrix = body_borrow.position().rotation.submatrix();
        let y = matrix.m12;
        let x = matrix.m11;
        *game_object.transform.mut_rotation() = y.atan2(x);
    }
}

pub fn copy_to_physics(game_object: &mut GameObject) {
    if let Some(ref mut body_box) = game_object.body {
        body_box.borrow_mut().set_transformation(Matrix::<f64> {
            rotation: Rotation2::new(Vector1 { x: *game_object.transform.rotation() }),
            translation: Vector2 {
                x: *game_object.transform.x(),
                y: *game_object.transform.y(),
            },
        });
    }
}
<commit_msg>Setup component execution ordering<commit_after>use app::App;
use texture::Texture;
use transform::Transform;
use component::Component;
use component::Message;
use std::collections::BTreeMap;
use std::mem;
use physics::nphysics2d::object::{RigidBody, RigidBodyHandle};
use physics::nphysics2d::math::Matrix;
use physics::nalgebra::{Rotation2, Vector2, Vector1};

pub struct GameObject {
    pub transform: Transform,
    pub texture: Texture,
    body: Option<RigidBodyHandle<f64>>,
    // When searching for a component associated with a GameObject you will need to search both of
    // these collections. At any given time either one of them could contain the Component you are
    // searching for. As messages are distributed to components they are migrated from
    // components to messaged_components and once the distribution of a message is complete
    // the two collections are swapped.
    components: BTreeMap<i32, Box<Component>>, // These have not had a message sent (yet).
    messaged_components: BTreeMap<i32, Box<Component>>, // These have had a message sent.
}

impl GameObject {
    pub fn new(app: &mut App) -> GameObject {
        GameObject {
            transform: Transform::new(),
            components: BTreeMap::new(),
            messaged_components: BTreeMap::new(),
            texture: Texture::empty(app),
            body: None,
        }
    }

    pub fn update(&mut self, app: &mut App, delta_time: f64) {
        let message = &Message::Update { delta_time: delta_time };
        for key in self.components.keys().map(|x| *x).collect::<Vec<i32>>() {
            if let Some(mut component) = self.components.remove(&key) {
                component.receive_message(app, self, &message);
                self.messaged_components.insert(key, component);
            }
        }
        assert_eq!(self.components.len(), 0);
        mem::swap(&mut self.components, &mut self.messaged_components);
    }

    pub fn component_indices(&self) -> Vec<i32> {
        self.components.keys().map(|x| *x).collect::<Vec<i32>>()
    }

    pub fn get_component(&self, index: i32) -> Option<&Box<Component>> {
        self.components.get(&index)
    }

    pub fn add_component_at_index(&mut self, component: Box<Component>, index: i32) {
        self.components.insert(index, component);
    }

    pub fn add_component(&mut self, component: Box<Component>) {
        let new_key = self.components.keys().nth(0).unwrap_or(&1) - 1;
        self.components.insert(new_key, component);
    }

    pub fn set_rigid_body(&mut self, app: &mut App, rigid_body: RigidBody<f64>) {
        self.body = Some(app.world.add_rigid_body(rigid_body));
    }
}

pub fn copy_from_physics(game_object: &mut GameObject) {
    if let &Some(ref body_box) = &game_object.body {
        let body_borrow = body_box.borrow();
        *game_object.transform.mut_x() = body_borrow.position().translation.x;
        *game_object.transform.mut_y() = body_borrow.position().translation.y;
        let matrix = body_borrow.position().rotation.submatrix();
        let y = matrix.m12;
        let x = matrix.m11;
        *game_object.transform.mut_rotation() = y.atan2(x);
    }
}

pub fn copy_to_physics(game_object: &mut GameObject) {
    if let Some(ref mut body_box) = game_object.body {
        body_box.borrow_mut().set_transformation(Matrix::<f64> {
            rotation: Rotation2::new(Vector1 { x: *game_object.transform.rotation() }),
            translation: Vector2 {
                x: *game_object.transform.x(),
                y: *game_object.transform.y(),
            },
        });
    }
}
<|endoftext|>


<commit_before>use std::cast;
use std::c_str::CString;
use std::i32;
use std::libc::*;
use std::num::Zero;
use std::ptr;
use std::vec;

use internal::bitmap::*;
use internal::bitmap_like::*;
use internal::color::*;
use internal::core_drawing::*;
use internal::events::*;

use ffi::*;

pub use self::display_flag::*;
pub use rust_util::c_bool;

pub mod external
{
	pub use super::display_flag::*;
	pub use super::{Display, DisplayOption, DisplayOptionImportance, DisplayOrientation};
}

flag_type!(
	mod display_flag
	{
		DisplayFlags
		{
			WINDOWED                  = ALLEGRO_WINDOWED,
			FULLSCREEN                = ALLEGRO_FULLSCREEN,
			OPENGL                    = ALLEGRO_OPENGL,
			DIRECT3D                  = ALLEGRO_DIRECT3D_INTERNAL,
			RESIZABLE                 = ALLEGRO_RESIZABLE,
			FRAMELESS                 = ALLEGRO_FRAMELESS,
			GENERATE_EXPOSE_EVENTS    = ALLEGRO_GENERATE_EXPOSE_EVENTS,
			OPENGL_3_0                = ALLEGRO_OPENGL_3_0,
			OPENGL_FORWARD_COMPATIBLE = ALLEGRO_OPENGL_FORWARD_COMPATIBLE,
			FULLSCREEN_WINDOW         = ALLEGRO_FULLSCREEN_WINDOW,
			MINIMIZED                 = ALLEGRO_MINIMIZED
		}
	}
)

pub enum DisplayOption
{
	RedSize = ALLEGRO_RED_SIZE,
	GreenSize = ALLEGRO_GREEN_SIZE,
	BlueSize = ALLEGRO_BLUE_SIZE,
	AlphaSize = ALLEGRO_ALPHA_SIZE,
	RedShift = ALLEGRO_RED_SHIFT,
	GreenShift = ALLEGRO_GREEN_SHIFT,
	BlueShift = ALLEGRO_BLUE_SHIFT,
	AlphaShift = ALLEGRO_ALPHA_SHIFT,
	AccRedSize = ALLEGRO_ACC_RED_SIZE,
	AccGreenSize = ALLEGRO_ACC_GREEN_SIZE,
	AccBlueSize = ALLEGRO_ACC_BLUE_SIZE,
	AccAlphaSize = ALLEGRO_ACC_ALPHA_SIZE,
	Stereo = ALLEGRO_STEREO,
	AuxBuffers = ALLEGRO_AUX_BUFFERS,
	ColorSize = ALLEGRO_COLOR_SIZE,
	DepthSize = ALLEGRO_DEPTH_SIZE,
	StencilSize = ALLEGRO_STENCIL_SIZE,
	SampleBuffers = ALLEGRO_SAMPLE_BUFFERS,
	Samples = ALLEGRO_SAMPLES,
	RenderMethod = ALLEGRO_RENDER_METHOD,
	FloatColor = ALLEGRO_FLOAT_COLOR,
	FloatDepth = ALLEGRO_FLOAT_DEPTH,
	SingleBuffer = ALLEGRO_SINGLE_BUFFER,
	SwapMethod = ALLEGRO_SWAP_METHOD,
	CompatibleDisplay = ALLEGRO_COMPATIBLE_DISPLAY,
	UpdateDisplayRegion = ALLEGRO_UPDATE_DISPLAY_REGION,
	Vsync = ALLEGRO_VSYNC,
	MaxBitmapSize = ALLEGRO_MAX_BITMAP_SIZE,
	SupportNpotBitmap = ALLEGRO_SUPPORT_NPOT_BITMAP,
	CanDrawIntoBitmap = ALLEGRO_CAN_DRAW_INTO_BITMAP,
	SupportSeparateAlpha = ALLEGRO_SUPPORT_SEPARATE_ALPHA,
}

pub enum DisplayOptionImportance
{
	DontCare = ALLEGRO_DONTCARE,
	Require = ALLEGRO_REQUIRE,
	Suggest = ALLEGRO_SUGGEST,
}

pub enum DisplayOrientation
{
	DisplayOrientation0Degrees = ALLEGRO_DISPLAY_ORIENTATION_0_DEGREES,
	DisplayOrientation90Degrees = ALLEGRO_DISPLAY_ORIENTATION_90_DEGREES,
	DisplayOrientation180Degrees = ALLEGRO_DISPLAY_ORIENTATION_180_DEGREES,
	DisplayOrientation270Degrees = ALLEGRO_DISPLAY_ORIENTATION_270_DEGREES,
	DisplayOrientationFaceUp = ALLEGRO_DISPLAY_ORIENTATION_FACE_UP,
	DisplayOrientationFaceDown = ALLEGRO_DISPLAY_ORIENTATION_FACE_DOWN,
}

pub struct DisplayOptions<'self>
{
	flags: DisplayFlags,
	refresh_rate: Option<i32>,
	adapter: Option<i32>,
	window_position: Option<[i32, ..2]>,
	options: Option<&'self [(DisplayOption, i32, DisplayOptionImportance)]>
}

impl<'self> DisplayOptions<'self>
{
	fn new() -> DisplayOptions
	{
		DisplayOptions{ flags: Zero::zero(), refresh_rate: None, adapter: None, window_position: None, options: None }
	}
}

pub struct Display
{
	priv allegro_display: *mut ALLEGRO_DISPLAY,
	priv backbuffer: Bitmap,
	priv event_source: EventSource
}

impl Display
{
	fn select_this_display(&self)
	{
		unsafe
		{
			if self.allegro_display != al_get_current_display()
			{
				al_set_target_bitmap(al_get_backbuffer(self.allegro_display))
			}
		}
	}

	pub fn get_width(&self) -> f32
	{
		unsafe
		{
			al_get_display_width(self.allegro_display) as f32
		}
	}

	pub fn get_height(&self) -> f32
	{
		unsafe
		{
			al_get_display_height(self.allegro_display) as f32
		}
	}

	pub fn get_format(&self) -> PixelFormat
	{
		unsafe
		{
			cast::transmute(al_get_display_format(self.allegro_display) as u64)
		}
	}

	pub fn get_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_display_refresh_rate(self.allegro_display) as i32
		}
	}

	pub fn get_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			cast::transmute(al_get_display_flags(self.allegro_display))
		}
	}

	pub fn set_flag(&self, flag: DisplayFlags, onoff: bool) -> bool
	{
		unsafe
		{
			al_set_display_flag(self.allegro_display, flag.get(), onoff as u8) != 0
		}
	}

	pub fn get_backbuffer<'l>(&'l self) -> &'l Bitmap
	{
		&self.backbuffer
	}

	pub fn acknowledge_resize(&self) -> bool
	{
		unsafe
		{
			al_acknowledge_resize(self.allegro_display) != 0
		}
	}

	pub fn resize(&self, w: i32, h: i32) -> bool
	{
		unsafe
		{
			al_resize_display(self.allegro_display, w as c_int, h as c_int) != 0
		}
	}

	pub fn flip(&self)
	{
		self.select_this_display();
		unsafe
		{
			al_flip_display();
		}
	}

	pub fn update_region(&self, x: i32, y: i32, width: i32, height: i32)
	{
		self.select_this_display();
		unsafe
		{
			al_update_display_region(x as c_int, y as c_int, width as c_int, height as c_int);
		}
	}

	pub fn is_compatible_bitmap<T: BitmapLike>(&self, bitmap: &T) -> bool
	{
		self.select_this_display();
		unsafe
		{
			al_is_compatible_bitmap(bitmap.get_bitmap()) != 0
		}
	}

	pub fn wait_for_vsync(&self) -> bool
	{
		self.select_this_display();
		unsafe
		{
			al_wait_for_vsync() != 0
		}
	}

	pub fn set_icon<T: BitmapLike>(&self, icon: &T)
	{
		unsafe
		{
			al_set_display_icon(self.allegro_display, icon.get_bitmap());
		}
	}

	pub fn set_icons<T: BitmapLike, U: Iterator<T>>(&self, mut icons: U)
	{
		let mut c_icons: ~[*mut ALLEGRO_BITMAP] = ~[];
		for icon in icons
		{
			c_icons.push(icon.get_bitmap());
		}
		unsafe
		{
			al_set_display_icons(self.allegro_display, c_icons.len() as c_int, vec::raw::to_mut_ptr(c_icons));
		}
	}

	pub fn set_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_window_position(self.allegro_display, x as c_int, y as c_int);
		}
	}

	pub fn get_window_position(&self) -> [i32, ..2]
	{
		unsafe
		{
			let mut x = 0 as c_int;
			let mut y = 0 as c_int;
			al_get_window_position(self.allegro_display, &mut x, &mut y);
			[x as i32, y as i32]
		}
	}

	pub fn set_window_title(&self, title: &CString)
	{
		unsafe
		{
			do title.with_ref |c_str|
			{
				al_set_window_title(self.allegro_display, c_str);
			}
		}
	}

	pub fn get_option(&self, option: DisplayOption) -> i32
	{
		unsafe
		{
			al_get_display_option(self.allegro_display, option as c_int) as i32
		}
	}

	pub fn hold_bitmap_drawing(&self, hold: bool)
	{
		self.select_this_display();
		unsafe
		{
			al_hold_bitmap_drawing(hold as c_bool);
		}
	}

	pub fn is_bitmap_drawing_held(&self) -> bool
	{
		self.select_this_display();
		unsafe
		{
			al_is_bitmap_drawing_held() != 0
		}
	}

	pub fn clone_convert<T: BitmapLike>(&self, bmp: &T) -> Option<Bitmap>
	{
		self.select_this_display();
		clone_bitmap(bmp.get_bitmap())
	}

	pub fn get_event_source<'l>(&'l self) -> &'l EventSource
	{
		&'l self.event_source
	}

	pub fn get_allegro_display(&self) -> *mut ALLEGRO_DISPLAY
	{
		self.allegro_display
	}
}

impl Drop for Display
{
	fn drop(&mut self)
	{
		unsafe
		{
			al_destroy_display(self.allegro_display);
		}
	}
}

impl DrawTarget for Display
{
	fn get_target_bitmap(&self) -> *mut ALLEGRO_BITMAP
	{
		unsafe
		{
			al_get_backbuffer(self.allegro_display)
		}
	}
}

impl CoreDrawing for Display {}

pub fn new_display(w: i32, h: i32) -> Option<Display>
{
	unsafe
	{
		let d = al_create_display(w as c_int, h as c_int);
		if ptr::is_null(d)
		{
			None
		}
		else
		{
			Some(Display{ allegro_display: d, backbuffer: new_bitmap_ref(al_get_backbuffer(d)),
								 event_source: new_event_source_ref(al_get_display_event_source(d)) })
		}
	}
}

pub fn new_display_with_options(w: i32, h: i32, opt: &DisplayOptions) -> Option<Display>
{
	unsafe
	{
		al_set_new_display_flags(opt.flags.get() as c_int);

		match opt.refresh_rate
		{
			Some(r) => al_set_new_display_refresh_rate(r as c_int),
			None => al_set_new_display_refresh_rate(0)
		}

		match opt.adapter
		{
			Some(a) => al_set_new_display_adapter(a as c_int),
			None => al_set_new_display_adapter(ALLEGRO_DEFAULT_DISPLAY_ADAPTER),
		}

		match opt.window_position
		{
			Some([x, y]) =>	al_set_new_window_position(x as c_int, y as c_int),
			None =>	al_set_new_window_position(i32::max_value, i32::max_value)
		}

		al_reset_new_display_options();

		match opt.options
		{
			Some(options) =>
			{
				for &(option, value, importance) in options.iter()
				{
					al_set_new_display_option(option as c_int, value as c_int, importance as c_int);
				}
			},
			None => ()
		}
	}

	new_display(w, h)
}
<commit_msg>Fix whitespace<commit_after>use std::cast;
use std::c_str::CString;
use std::i32;
use std::libc::*;
use std::num::Zero;
use std::ptr;
use std::vec;

use internal::bitmap::*;
use internal::bitmap_like::*;
use internal::color::*;
use internal::core_drawing::*;
use internal::events::*;

use ffi::*;

pub use self::display_flag::*;
pub use rust_util::c_bool;

pub mod external
{
	pub use super::display_flag::*;
	pub use super::{Display, DisplayOption, DisplayOptionImportance, DisplayOrientation};
}

flag_type!(
	mod display_flag
	{
		DisplayFlags
		{
			WINDOWED                  = ALLEGRO_WINDOWED,
			FULLSCREEN                = ALLEGRO_FULLSCREEN,
			OPENGL                    = ALLEGRO_OPENGL,
			DIRECT3D                  = ALLEGRO_DIRECT3D_INTERNAL,
			RESIZABLE                 = ALLEGRO_RESIZABLE,
			FRAMELESS                 = ALLEGRO_FRAMELESS,
			GENERATE_EXPOSE_EVENTS    = ALLEGRO_GENERATE_EXPOSE_EVENTS,
			OPENGL_3_0                = ALLEGRO_OPENGL_3_0,
			OPENGL_FORWARD_COMPATIBLE = ALLEGRO_OPENGL_FORWARD_COMPATIBLE,
			FULLSCREEN_WINDOW         = ALLEGRO_FULLSCREEN_WINDOW,
			MINIMIZED                 = ALLEGRO_MINIMIZED
		}
	}
)

pub enum DisplayOption
{
	RedSize = ALLEGRO_RED_SIZE,
	GreenSize = ALLEGRO_GREEN_SIZE,
	BlueSize = ALLEGRO_BLUE_SIZE,
	AlphaSize = ALLEGRO_ALPHA_SIZE,
	RedShift = ALLEGRO_RED_SHIFT,
	GreenShift = ALLEGRO_GREEN_SHIFT,
	BlueShift = ALLEGRO_BLUE_SHIFT,
	AlphaShift = ALLEGRO_ALPHA_SHIFT,
	AccRedSize = ALLEGRO_ACC_RED_SIZE,
	AccGreenSize = ALLEGRO_ACC_GREEN_SIZE,
	AccBlueSize = ALLEGRO_ACC_BLUE_SIZE,
	AccAlphaSize = ALLEGRO_ACC_ALPHA_SIZE,
	Stereo = ALLEGRO_STEREO,
	AuxBuffers = ALLEGRO_AUX_BUFFERS,
	ColorSize = ALLEGRO_COLOR_SIZE,
	DepthSize = ALLEGRO_DEPTH_SIZE,
	StencilSize = ALLEGRO_STENCIL_SIZE,
	SampleBuffers = ALLEGRO_SAMPLE_BUFFERS,
	Samples = ALLEGRO_SAMPLES,
	RenderMethod = ALLEGRO_RENDER_METHOD,
	FloatColor = ALLEGRO_FLOAT_COLOR,
	FloatDepth = ALLEGRO_FLOAT_DEPTH,
	SingleBuffer = ALLEGRO_SINGLE_BUFFER,
	SwapMethod = ALLEGRO_SWAP_METHOD,
	CompatibleDisplay = ALLEGRO_COMPATIBLE_DISPLAY,
	UpdateDisplayRegion = ALLEGRO_UPDATE_DISPLAY_REGION,
	Vsync = ALLEGRO_VSYNC,
	MaxBitmapSize = ALLEGRO_MAX_BITMAP_SIZE,
	SupportNpotBitmap = ALLEGRO_SUPPORT_NPOT_BITMAP,
	CanDrawIntoBitmap = ALLEGRO_CAN_DRAW_INTO_BITMAP,
	SupportSeparateAlpha = ALLEGRO_SUPPORT_SEPARATE_ALPHA,
}

pub enum DisplayOptionImportance
{
	DontCare = ALLEGRO_DONTCARE,
	Require = ALLEGRO_REQUIRE,
	Suggest = ALLEGRO_SUGGEST,
}

pub enum DisplayOrientation
{
	DisplayOrientation0Degrees = ALLEGRO_DISPLAY_ORIENTATION_0_DEGREES,
	DisplayOrientation90Degrees = ALLEGRO_DISPLAY_ORIENTATION_90_DEGREES,
	DisplayOrientation180Degrees = ALLEGRO_DISPLAY_ORIENTATION_180_DEGREES,
	DisplayOrientation270Degrees = ALLEGRO_DISPLAY_ORIENTATION_270_DEGREES,
	DisplayOrientationFaceUp = ALLEGRO_DISPLAY_ORIENTATION_FACE_UP,
	DisplayOrientationFaceDown = ALLEGRO_DISPLAY_ORIENTATION_FACE_DOWN,
}

pub struct DisplayOptions<'self>
{
	flags: DisplayFlags,
	refresh_rate: Option<i32>,
	adapter: Option<i32>,
	window_position: Option<[i32, ..2]>,
	options: Option<&'self [(DisplayOption, i32, DisplayOptionImportance)]>
}

impl<'self> DisplayOptions<'self>
{
	fn new() -> DisplayOptions
	{
		DisplayOptions{ flags: Zero::zero(), refresh_rate: None, adapter: None, window_position: None, options: None }
	}
}

pub struct Display
{
	priv allegro_display: *mut ALLEGRO_DISPLAY,
	priv backbuffer: Bitmap,
	priv event_source: EventSource
}

impl Display
{
	fn select_this_display(&self)
	{
		unsafe
		{
			if self.allegro_display != al_get_current_display()
			{
				al_set_target_bitmap(al_get_backbuffer(self.allegro_display))
			}
		}
	}

	pub fn get_width(&self) -> f32
	{
		unsafe
		{
			al_get_display_width(self.allegro_display) as f32
		}
	}

	pub fn get_height(&self) -> f32
	{
		unsafe
		{
			al_get_display_height(self.allegro_display) as f32
		}
	}

	pub fn get_format(&self) -> PixelFormat
	{
		unsafe
		{
			cast::transmute(al_get_display_format(self.allegro_display) as u64)
		}
	}

	pub fn get_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_display_refresh_rate(self.allegro_display) as i32
		}
	}

	pub fn get_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			cast::transmute(al_get_display_flags(self.allegro_display))
		}
	}

	pub fn set_flag(&self, flag: DisplayFlags, onoff: bool) -> bool
	{
		unsafe
		{
			al_set_display_flag(self.allegro_display, flag.get(), onoff as u8) != 0
		}
	}

	pub fn get_backbuffer<'l>(&'l self) -> &'l Bitmap
	{
		&self.backbuffer
	}

	pub fn acknowledge_resize(&self) -> bool
	{
		unsafe
		{
			al_acknowledge_resize(self.allegro_display) != 0
		}
	}

	pub fn resize(&self, w: i32, h: i32) -> bool
	{
		unsafe
		{
			al_resize_display(self.allegro_display, w as c_int, h as c_int) != 0
		}
	}

	pub fn flip(&self)
	{
		self.select_this_display();
		unsafe
		{
			al_flip_display();
		}
	}

	pub fn update_region(&self, x: i32, y: i32, width: i32, height: i32)
	{
		self.select_this_display();
		unsafe
		{
			al_update_display_region(x as c_int, y as c_int, width as c_int, height as c_int);
		}
	}

	pub fn is_compatible_bitmap<T: BitmapLike>(&self, bitmap: &T) -> bool
	{
		self.select_this_display();
		unsafe
		{
			al_is_compatible_bitmap(bitmap.get_bitmap()) != 0
		}
	}

	pub fn wait_for_vsync(&self) -> bool
	{
		self.select_this_display();
		unsafe
		{
			al_wait_for_vsync() != 0
		}
	}

	pub fn set_icon<T: BitmapLike>(&self, icon: &T)
	{
		unsafe
		{
			al_set_display_icon(self.allegro_display, icon.get_bitmap());
		}
	}

	pub fn set_icons<T: BitmapLike, U: Iterator<T>>(&self, mut icons: U)
	{
		let mut c_icons: ~[*mut ALLEGRO_BITMAP] = ~[];
		for icon in icons
		{
			c_icons.push(icon.get_bitmap());
		}
		unsafe
		{
			al_set_display_icons(self.allegro_display, c_icons.len() as c_int, vec::raw::to_mut_ptr(c_icons));
		}
	}

	pub fn set_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_window_position(self.allegro_display, x as c_int, y as c_int);
		}
	}

	pub fn get_window_position(&self) -> [i32, ..2]
	{
		unsafe
		{
			let mut x = 0 as c_int;
			let mut y = 0 as c_int;
			al_get_window_position(self.allegro_display, &mut x, &mut y);
			[x as i32, y as i32]
		}
	}

	pub fn set_window_title(&self, title: &CString)
	{
		unsafe
		{
			do title.with_ref |c_str|
			{
				al_set_window_title(self.allegro_display, c_str);
			}
		}
	}

	pub fn get_option(&self, option: DisplayOption) -> i32
	{
		unsafe
		{
			al_get_display_option(self.allegro_display, option as c_int) as i32
		}
	}

	pub fn hold_bitmap_drawing(&self, hold: bool)
	{
		self.select_this_display();
		unsafe
		{
			al_hold_bitmap_drawing(hold as c_bool);
		}
	}

	pub fn is_bitmap_drawing_held(&self) -> bool
	{
		self.select_this_display();
		unsafe
		{
			al_is_bitmap_drawing_held() != 0
		}
	}

	pub fn clone_convert<T: BitmapLike>(&self, bmp: &T) -> Option<Bitmap>
	{
		self.select_this_display();
		clone_bitmap(bmp.get_bitmap())
	}

	pub fn get_event_source<'l>(&'l self) -> &'l EventSource
	{
		&'l self.event_source
	}

	pub fn get_allegro_display(&self) -> *mut ALLEGRO_DISPLAY
	{
		self.allegro_display
	}
}

impl Drop for Display
{
	fn drop(&mut self)
	{
		unsafe
		{
			al_destroy_display(self.allegro_display);
		}
	}
}

impl DrawTarget for Display
{
	fn get_target_bitmap(&self) -> *mut ALLEGRO_BITMAP
	{
		unsafe
		{
			al_get_backbuffer(self.allegro_display)
		}
	}
}

impl CoreDrawing for Display {}

pub fn new_display(w: i32, h: i32) -> Option<Display>
{
	unsafe
	{
		let d = al_create_display(w as c_int, h as c_int);
		if ptr::is_null(d)
		{
			None
		}
		else
		{
			Some(Display{ allegro_display: d, backbuffer: new_bitmap_ref(al_get_backbuffer(d)),
			              event_source: new_event_source_ref(al_get_display_event_source(d)) })
		}
	}
}

pub fn new_display_with_options(w: i32, h: i32, opt: &DisplayOptions) -> Option<Display>
{
	unsafe
	{
		al_set_new_display_flags(opt.flags.get() as c_int);

		match opt.refresh_rate
		{
			Some(r) => al_set_new_display_refresh_rate(r as c_int),
			None => al_set_new_display_refresh_rate(0)
		}

		match opt.adapter
		{
			Some(a) => al_set_new_display_adapter(a as c_int),
			None => al_set_new_display_adapter(ALLEGRO_DEFAULT_DISPLAY_ADAPTER),
		}

		match opt.window_position
		{
			Some([x, y]) =>	al_set_new_window_position(x as c_int, y as c_int),
			None =>	al_set_new_window_position(i32::max_value, i32::max_value)
		}

		al_reset_new_display_options();

		match opt.options
		{
			Some(options) =>
			{
				for &(option, value, importance) in options.iter()
				{
					al_set_new_display_option(option as c_int, value as c_int, importance as c_int);
				}
			},
			None => ()
		}
	}

	new_display(w, h)
}
<|endoftext|>


<commit_before>// Used internally for evalulating expressions

use super::lexer::{Token, TokenType};
use super::{CompileError, SourcePos, from_bool, is_truthy};
use super::scope::Scope;
use super::function::{Function, SyntFunctionCall};
use std::num::Float;

#[deriving(Show, Clone)]
enum ExprToken<'a> {
	Op(Operator),
	Value(f32),
	Var(uint),
	LParen,
	RParen,
	Fn(SyntFunctionCall<'a>),
}

#[deriving(Show, Clone)]
enum Operator {
	Add,
	Sub,
	Mul,
	Div,
	Exp,
	Mod,
	Neg,
	Less,
	Greater,
	Equ,
	NotEqu,
	ApproxEqu,
	Not,
	And,
	Or,
	Xor,
	GreaterEqual,
	LessEqual,
}

#[deriving(PartialEq)]
enum Associativity {
	Left,
	Right,
}

impl Operator {
	fn precedence(self) -> int {
		use self::Operator::*;
		match self {
			And | Or | Xor => 0,
			Equ | NotEqu | ApproxEqu => 1,
			Less | Greater | GreaterEqual | LessEqual => 2,
			Add | Sub => 3,
			Mul | Div | Mod => 4,
			Neg | Not | Exp => 6,
		}
	}

	fn num_args(self) -> uint {
		use self::Operator::*;
		match self {
			Neg | Not => 1,
			_ => 2,
		}
	}

	fn associativity(self) -> Associativity {
		use self::Operator::*;
		match self {
			Exp => Associativity::Right,
			_ => Associativity::Left,
		}
	}
}

/// An expression is a mathematical statement containing a number of operators, constants and
/// variables. It evaluates to a single number.
#[deriving(Show, Clone)]
pub struct Expression<'a> {
	rpn: Vec<ExprToken<'a>>, // reverse polish notation
	pos: SourcePos,
}

impl<'a> Expression<'a> {
	/// Converts a token slice from the lexer into an expression that can be evaluated
	pub fn new(tok: &'a [Token<'a>], scope: &'a Scope<'a>) -> Result<Expression<'a>, CompileError> {
		let out = try!(to_expr_tokens(tok, scope));
		let out = match shunting_yard(out.as_slice()) {
			Ok(out) => out,
			Err(e) => return Err(CompileError { msg: e.to_string(), pos: Some(tok[0].pos) })
		};

		Ok(Expression {
			rpn: out,
			pos: tok[0].pos, // Point to the location in the source that the expression started at.
		})
	}

	/// Replaces variables with their values in the given scope
	pub fn fold_scope(&mut self, scope: &Scope) {
		for tok in self.rpn.iter_mut() {
			match tok {
				&ExprToken::Var(id) => {
					match scope.get_var(id) {
						Some(id) => *tok = ExprToken::Value(id),
						None => { }
					}
				},
				_ => { }
			}
		}
	}

	/// Evaluates the value of the expression
	pub fn eval<'s>(&self, scope: &'s Scope<'s>) -> Result<f32, CompileError> {
		match eval_rpn(self.rpn.as_slice(), scope) {
			Ok(val) => Ok(val),
			Err(e) => Err(CompileError { msg: e, pos: Some(self.pos) }),
		}
	}
}

// Converts tokens from the lexer into ExprTokens, which are simplified to drop any strings and
// contain only information understandable by the expression parser. Any variables encountered are
// defined in the scope.
fn to_expr_tokens<'a>(tok: &'a [Token<'a>], scope: &'a Scope<'a>) -> Result<Vec<ExprToken<'a>>, CompileError> {
	if tok.is_empty() {
		return Err(CompileError { msg: "empty expression in file".to_string(), pos: None });
	}
	let mut out = Vec::new();

	let mut iter = tok.iter().peekable();
	let mut index = 0u;
	loop {
		let t = match iter.next() {
			Some(t) => t,
			None => break,
		};
		match t.t {
			// Try to parse constants as f32. subject to maybe change but probably not.
			TokenType::Const(v) => {
				out.push(ExprToken::Value(v))
			},
			TokenType::Operator(v) => {
				use self::Operator::*;
				out.push(ExprToken::Op(match v {
					"+" => Add,
					"-" => Sub,
					"*" => Mul,
					"/" => Div,
					"^" => Exp,
					"%" => Mod,
					"==" => Equ,
					"!=" => NotEqu,
					"~=" => ApproxEqu,
					"<" => Less,
					">" => Greater,
					"<=" => LessEqual,
					">=" => GreaterEqual,
					"!" => Not,
					"&&" => And,
					"||" => Or,
					"^^" => Xor,
					x => {
						return Err(CompileError { msg: format!("unexpected operator in expression: `{}`", x), pos: Some(t.pos) });
					}
				}))
			},
			TokenType::Paren(v) => {
				out.push(match v {
					'(' => ExprToken::LParen,
					')' => ExprToken::RParen,
					x => {
						return Err(CompileError { msg: format!("unexpected paren type in expression: `{}`", x), pos: Some(t.pos) });
					}
				})
			},
			// An identifier in the context of an expression is always a variable except for when
			// it's a function.
			TokenType::Ident(v) => {
				let is_fn = if let Some(t) = iter.peek() { t.t == TokenType::Paren('(') } else { false };

				if is_fn {
					let call_start = index;
					let mut call_end = index;
					let mut depth = 0u;
					loop {
						match iter.next() {
							Some(token) => {
								match token.t {
									TokenType::Paren('(') => depth += 1,
									TokenType::Paren(')') => depth -= 1,
									_ => { },
								}
								call_end += 1;
								index += 1;
							},
							None => return Err(CompileError { msg: format!("unexpected end of file in function call"), pos: Some(t.pos) })
						}
						if depth == 0 {
							break;
						}
					}
					match scope.func_id(v) {
						Some(_) => {
							let func = try!(SyntFunctionCall::new(tok[call_start..call_end + 1], scope));
							out.push(ExprToken::Fn(func));
						},
						None => {
							return Err(CompileError { msg: format!("function `{}` appears in expression but is not defined in scope", v), pos: Some(t.pos) })
						}
					}
				} else {
					match scope.var_id(v) {
						Some(id) => out.push(ExprToken::Var(id)),
						None => {
							return Err(CompileError { msg: format!("variable `{}` appears in expression but is not defined in scope", v), pos: Some(t.pos) })
						}
					}
				}
			},
			// Discard whitesapce
			TokenType::Newline => { },

			x => {
				return Err(CompileError { msg: format!("unexpected token in expression `{}`", x), pos: Some(t.pos) });
			}
		}
		index += 1;
	}

	// Handle special case with unary minus
	// If an subtraction operator is preceded by another operator, left paren, or the start of the
	// expression, make it a negation operator.
	// would be nice if you could use map_in_place here, but can't because of enumerate.
	/*let out: Vec<ExprToken> = out.iter().enumerate().map(|(i, &v)| {
		match v {
			Op(Sub) => {
				if i == 0 || match out[i-1] { Op(_) | LParen => true, _ => false } {
					Op(Neg)
				} else {
					v
				}
			},
			_ => v
		}
	}).collect();*/

	for i in range(0, out.len()) {
		match out[i] {
			ExprToken::Op(Operator::Sub) => {
				if i == 0 || match out[i - 1] { ExprToken::Op(_) | ExprToken::LParen => true, _ => false } {
					out[i] = ExprToken::Op(Operator::Neg);
				}
			}
			_ => { }
		}
	}

	Ok(out)
}

// http://en.wikipedia.org/wiki/Shunting-yard_algorithm
fn shunting_yard<'a>(tok: &[ExprToken<'a>]) -> Result<Vec<ExprToken<'a>>, &'static str> {
	let mut out = Vec::new();
	let mut stack: Vec<ExprToken> = Vec::new();

	for t in tok.iter() {
		match t {
			&ExprToken::Value(_) | &ExprToken::Var(_) | &ExprToken::Fn(_) => {
				out.push(t.clone());
			},

			&ExprToken::Op(op1) => {
				while stack.len() > 0 {
					let top = stack.last().unwrap().clone(); // unwrap() can't fail, see condition on while loop
					match top {
						ExprToken::Op(op2) => {
							if op1.associativity() == Associativity::Left && op1.precedence() <= op2.precedence()
								|| op1.precedence() < op2.precedence() {
								stack.pop();
								out.push(top.clone());
							} else {
								break;
							}
						},
						_ => break
					}
				}
				stack.push(t.clone());
			},

			&ExprToken::LParen => {
				stack.push(t.clone());
			},

			&ExprToken::RParen => {
				let mut foundleft = false;
				while stack.len() > 0 {
					let op = stack.pop().unwrap();
					match op {
						ExprToken::Op(_) => {
							out.push(op.clone());
						},
						ExprToken::LParen => {
							foundleft = true;
							break;
						},
						x => panic!("internal error: unexpected value on stack: `{}`", x)
					}
				}
				if !foundleft {
					return Err("mismatched parens: skewed right");
				}
			}
		};
	}

	while stack.len() > 0 {
		let top = stack[stack.len()-1].clone();
		match top {
			ExprToken::Op(_) => {
				stack.pop();
				out.push(top.clone());
			},
			ExprToken::LParen | ExprToken::RParen => return Err("mismatched parens: skewed left"),
			x => panic!("internal error: non operator on stack: `{}`", x)
		}
	}

	Ok(out)
}

// http://en.wikipedia.org/wiki/Reverse_Polish_notation
fn eval_rpn<'s>(rpn: &[ExprToken], scope: &'s Scope<'s>) -> Result<f32, String> {
	let mut stack = Vec::new();

	for t in rpn.iter() {
		match t {
			&ExprToken::Value(v) => {
				stack.push(v);
			},

			&ExprToken::Fn(ref v) => {
				stack.push(match v.call(scope) {
					Ok(v) => v,
					Err(e) => return Err(format!("{}", e)),
				});
			}

			&ExprToken::Var(id) => {
				match scope.get_var(id) {
					Some(val) => stack.push(val),
					None => return Err(format!("Attempted to access a nonexistent variable (id={})", id))
				}
			},

			&ExprToken::Op(op) => {
				use self::Operator::*;

				// Pop args off stack
				let n = op.num_args();
				if stack.len() < n {
					return Err(format!("invalid expression: not enough args for operator {}", op));
				}
				// unwrap() can't fail because of the size check above.
				let args: Vec<f32> = range(0, n).map(|_| stack.pop().unwrap()).collect();

				// Do calculation and push result
				stack.push(match op {
					Add => {
						args[1] + args[0]
					},
					Sub => {
						args[1] - args[0]
					},
					Mul => {
						args[1] * args[0]
					},
					Div => {
						args[1] / args[0]
					},
					Exp => {
						args[1].powf(args[0])
					},
					Mod => {
						let c = (args[1]/args[0]).abs().fract()*args[0].abs();
						if args[1] > 0_f32 { c } else { -c }
					},
					Neg => {
						-args[0]
					},
					Not => {
						from_bool(is_truthy(-args[0]))
					},
					Less => {
						from_bool(args[1] < args[0])
					},
					Greater => {
						from_bool(args[1] > args[0])
					},
					LessEqual => {
						from_bool(args[1] <= args[0])
					},
					GreaterEqual => {
						from_bool(args[1] >= args[0])
					},
					Equ => {
						from_bool(args[1] == args[0])
					},
					NotEqu => {
						from_bool(args[1] != args[0])
					},
					ApproxEqu => {
						from_bool((args[1] - args[0]).abs() < 0.0001)
					},
					And => {
						from_bool(is_truthy(args[1]) && is_truthy(args[0]))
					},
					Or => {
						from_bool(is_truthy(args[1]) || is_truthy(args[0]))
					},
					Xor => {
						from_bool(is_truthy(args[1]) ^ is_truthy(args[0]))
					},
				});
			},

			x => return Err(format!("unexpected token in expression: `{}`", x))
		}
	}
	match stack.len() {
		1 => {
			let val = stack.pop().unwrap();
			Ok(val)
		},
		0 => {
			Err("zero values in expression".to_string())
		},
		_ => {
			Err("too many values in expression".to_string())
		}
	}
}
<commit_msg>Remove some commented out code that has been improved<commit_after>// Used internally for evalulating expressions

use super::lexer::{Token, TokenType};
use super::{CompileError, SourcePos, from_bool, is_truthy};
use super::scope::Scope;
use super::function::{Function, SyntFunctionCall};
use std::num::Float;

#[deriving(Show, Clone)]
enum ExprToken<'a> {
	Op(Operator),
	Value(f32),
	Var(uint),
	LParen,
	RParen,
	Fn(SyntFunctionCall<'a>),
}

#[deriving(Show, Clone)]
enum Operator {
	Add,
	Sub,
	Mul,
	Div,
	Exp,
	Mod,
	Neg,
	Less,
	Greater,
	Equ,
	NotEqu,
	ApproxEqu,
	Not,
	And,
	Or,
	Xor,
	GreaterEqual,
	LessEqual,
}

#[deriving(PartialEq)]
enum Associativity {
	Left,
	Right,
}

impl Operator {
	fn precedence(self) -> int {
		use self::Operator::*;
		match self {
			And | Or | Xor => 0,
			Equ | NotEqu | ApproxEqu => 1,
			Less | Greater | GreaterEqual | LessEqual => 2,
			Add | Sub => 3,
			Mul | Div | Mod => 4,
			Neg | Not | Exp => 6,
		}
	}

	fn num_args(self) -> uint {
		use self::Operator::*;
		match self {
			Neg | Not => 1,
			_ => 2,
		}
	}

	fn associativity(self) -> Associativity {
		use self::Operator::*;
		match self {
			Exp => Associativity::Right,
			_ => Associativity::Left,
		}
	}
}

/// An expression is a mathematical statement containing a number of operators, constants and
/// variables. It evaluates to a single number.
#[deriving(Show, Clone)]
pub struct Expression<'a> {
	rpn: Vec<ExprToken<'a>>, // reverse polish notation
	pos: SourcePos,
}

impl<'a> Expression<'a> {
	/// Converts a token slice from the lexer into an expression that can be evaluated
	pub fn new(tok: &'a [Token<'a>], scope: &'a Scope<'a>) -> Result<Expression<'a>, CompileError> {
		let out = try!(to_expr_tokens(tok, scope));
		let out = match shunting_yard(out.as_slice()) {
			Ok(out) => out,
			Err(e) => return Err(CompileError { msg: e.to_string(), pos: Some(tok[0].pos) })
		};

		Ok(Expression {
			rpn: out,
			pos: tok[0].pos, // Point to the location in the source that the expression started at.
		})
	}

	/// Replaces variables with their values in the given scope
	pub fn fold_scope(&mut self, scope: &Scope) {
		for tok in self.rpn.iter_mut() {
			match tok {
				&ExprToken::Var(id) => {
					match scope.get_var(id) {
						Some(id) => *tok = ExprToken::Value(id),
						None => { }
					}
				},
				_ => { }
			}
		}
	}

	/// Evaluates the value of the expression
	pub fn eval<'s>(&self, scope: &'s Scope<'s>) -> Result<f32, CompileError> {
		match eval_rpn(self.rpn.as_slice(), scope) {
			Ok(val) => Ok(val),
			Err(e) => Err(CompileError { msg: e, pos: Some(self.pos) }),
		}
	}
}

// Converts tokens from the lexer into ExprTokens, which are simplified to drop any strings and
// contain only information understandable by the expression parser. Any variables encountered are
// defined in the scope.
fn to_expr_tokens<'a>(tok: &'a [Token<'a>], scope: &'a Scope<'a>) -> Result<Vec<ExprToken<'a>>, CompileError> {
	if tok.is_empty() {
		return Err(CompileError { msg: "empty expression in file".to_string(), pos: None });
	}
	let mut out = Vec::new();

	let mut iter = tok.iter().peekable();
	let mut index = 0u;
	loop {
		let t = match iter.next() {
			Some(t) => t,
			None => break,
		};
		match t.t {
			// Try to parse constants as f32. subject to maybe change but probably not.
			TokenType::Const(v) => {
				out.push(ExprToken::Value(v))
			},
			TokenType::Operator(v) => {
				use self::Operator::*;
				out.push(ExprToken::Op(match v {
					"+" => Add,
					"-" => Sub,
					"*" => Mul,
					"/" => Div,
					"^" => Exp,
					"%" => Mod,
					"==" => Equ,
					"!=" => NotEqu,
					"~=" => ApproxEqu,
					"<" => Less,
					">" => Greater,
					"<=" => LessEqual,
					">=" => GreaterEqual,
					"!" => Not,
					"&&" => And,
					"||" => Or,
					"^^" => Xor,
					x => {
						return Err(CompileError { msg: format!("unexpected operator in expression: `{}`", x), pos: Some(t.pos) });
					}
				}))
			},
			TokenType::Paren(v) => {
				out.push(match v {
					'(' => ExprToken::LParen,
					')' => ExprToken::RParen,
					x => {
						return Err(CompileError { msg: format!("unexpected paren type in expression: `{}`", x), pos: Some(t.pos) });
					}
				})
			},
			// An identifier in the context of an expression is always a variable except for when
			// it's a function.
			TokenType::Ident(v) => {
				let is_fn = if let Some(t) = iter.peek() { t.t == TokenType::Paren('(') } else { false };

				if is_fn {
					let call_start = index;
					let mut call_end = index;
					let mut depth = 0u;
					loop {
						match iter.next() {
							Some(token) => {
								match token.t {
									TokenType::Paren('(') => depth += 1,
									TokenType::Paren(')') => depth -= 1,
									_ => { },
								}
								call_end += 1;
								index += 1;
							},
							None => return Err(CompileError { msg: format!("unexpected end of file in function call"), pos: Some(t.pos) })
						}
						if depth == 0 {
							break;
						}
					}
					match scope.func_id(v) {
						Some(_) => {
							let func = try!(SyntFunctionCall::new(tok[call_start..call_end + 1], scope));
							out.push(ExprToken::Fn(func));
						},
						None => {
							return Err(CompileError { msg: format!("function `{}` appears in expression but is not defined in scope", v), pos: Some(t.pos) })
						}
					}
				} else {
					match scope.var_id(v) {
						Some(id) => out.push(ExprToken::Var(id)),
						None => {
							return Err(CompileError { msg: format!("variable `{}` appears in expression but is not defined in scope", v), pos: Some(t.pos) })
						}
					}
				}
			},
			// Discard whitesapce
			TokenType::Newline => { },

			x => {
				return Err(CompileError { msg: format!("unexpected token in expression `{}`", x), pos: Some(t.pos) });
			}
		}
		index += 1;
	}

	// Handle special case with unary minus
	// If an subtraction operator is preceded by another operator, left paren, or the start of the
	// expression, make it a negation operator.
	// would be nice if you could use map_in_place here, but can't because of enumerate.
	for i in range(0, out.len()) {
		match out[i] {
			ExprToken::Op(Operator::Sub) => {
				if i == 0 || match out[i - 1] { ExprToken::Op(_) | ExprToken::LParen => true, _ => false } {
					out[i] = ExprToken::Op(Operator::Neg);
				}
			}
			_ => { }
		}
	}

	Ok(out)
}

// http://en.wikipedia.org/wiki/Shunting-yard_algorithm
fn shunting_yard<'a>(tok: &[ExprToken<'a>]) -> Result<Vec<ExprToken<'a>>, &'static str> {
	let mut out = Vec::new();
	let mut stack: Vec<ExprToken> = Vec::new();

	for t in tok.iter() {
		match t {
			&ExprToken::Value(_) | &ExprToken::Var(_) | &ExprToken::Fn(_) => {
				out.push(t.clone());
			},

			&ExprToken::Op(op1) => {
				while stack.len() > 0 {
					let top = stack.last().unwrap().clone(); // unwrap() can't fail, see condition on while loop
					match top {
						ExprToken::Op(op2) => {
							if op1.associativity() == Associativity::Left && op1.precedence() <= op2.precedence()
								|| op1.precedence() < op2.precedence() {
								stack.pop();
								out.push(top.clone());
							} else {
								break;
							}
						},
						_ => break
					}
				}
				stack.push(t.clone());
			},

			&ExprToken::LParen => {
				stack.push(t.clone());
			},

			&ExprToken::RParen => {
				let mut foundleft = false;
				while stack.len() > 0 {
					let op = stack.pop().unwrap();
					match op {
						ExprToken::Op(_) => {
							out.push(op.clone());
						},
						ExprToken::LParen => {
							foundleft = true;
							break;
						},
						x => panic!("internal error: unexpected value on stack: `{}`", x)
					}
				}
				if !foundleft {
					return Err("mismatched parens: skewed right");
				}
			}
		};
	}

	while stack.len() > 0 {
		let top = stack[stack.len()-1].clone();
		match top {
			ExprToken::Op(_) => {
				stack.pop();
				out.push(top.clone());
			},
			ExprToken::LParen | ExprToken::RParen => return Err("mismatched parens: skewed left"),
			x => panic!("internal error: non operator on stack: `{}`", x)
		}
	}

	Ok(out)
}

// http://en.wikipedia.org/wiki/Reverse_Polish_notation
fn eval_rpn<'s>(rpn: &[ExprToken], scope: &'s Scope<'s>) -> Result<f32, String> {
	let mut stack = Vec::new();

	for t in rpn.iter() {
		match t {
			&ExprToken::Value(v) => {
				stack.push(v);
			},

			&ExprToken::Fn(ref v) => {
				stack.push(match v.call(scope) {
					Ok(v) => v,
					Err(e) => return Err(format!("{}", e)),
				});
			}

			&ExprToken::Var(id) => {
				match scope.get_var(id) {
					Some(val) => stack.push(val),
					None => return Err(format!("Attempted to access a nonexistent variable (id={})", id))
				}
			},

			&ExprToken::Op(op) => {
				use self::Operator::*;

				// Pop args off stack
				let n = op.num_args();
				if stack.len() < n {
					return Err(format!("invalid expression: not enough args for operator {}", op));
				}
				// unwrap() can't fail because of the size check above.
				let args: Vec<f32> = range(0, n).map(|_| stack.pop().unwrap()).collect();

				// Do calculation and push result
				stack.push(match op {
					Add => {
						args[1] + args[0]
					},
					Sub => {
						args[1] - args[0]
					},
					Mul => {
						args[1] * args[0]
					},
					Div => {
						args[1] / args[0]
					},
					Exp => {
						args[1].powf(args[0])
					},
					Mod => {
						let c = (args[1]/args[0]).abs().fract()*args[0].abs();
						if args[1] > 0_f32 { c } else { -c }
					},
					Neg => {
						-args[0]
					},
					Not => {
						from_bool(is_truthy(-args[0]))
					},
					Less => {
						from_bool(args[1] < args[0])
					},
					Greater => {
						from_bool(args[1] > args[0])
					},
					LessEqual => {
						from_bool(args[1] <= args[0])
					},
					GreaterEqual => {
						from_bool(args[1] >= args[0])
					},
					Equ => {
						from_bool(args[1] == args[0])
					},
					NotEqu => {
						from_bool(args[1] != args[0])
					},
					ApproxEqu => {
						from_bool((args[1] - args[0]).abs() < 0.0001)
					},
					And => {
						from_bool(is_truthy(args[1]) && is_truthy(args[0]))
					},
					Or => {
						from_bool(is_truthy(args[1]) || is_truthy(args[0]))
					},
					Xor => {
						from_bool(is_truthy(args[1]) ^ is_truthy(args[0]))
					},
				});
			},

			x => return Err(format!("unexpected token in expression: `{}`", x))
		}
	}
	match stack.len() {
		1 => {
			let val = stack.pop().unwrap();
			Ok(val)
		},
		0 => {
			Err("zero values in expression".to_string())
		},
		_ => {
			Err("too many values in expression".to_string())
		}
	}
}
<|endoftext|>


<commit_before>use crossbeam_deque::{Deque, Stealer, Steal};

use std::thread::yield_now;
use std::sync::{Mutex, TryLockError};
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering};

use iter::*;
use current_num_threads;

/// Conversion trait to convert an `Iterator` to a `ParallelIterator`.
///
/// This needs to be distinct from `IntoParallelIterator` because that trait is already implemented
/// on a few `Iterator`s, like `std::ops::Range`.
pub trait AsParallel {
    /// What is the type of the output `ParallelIterator`?
    type Iter: ParallelIterator<Item = Self::Item>;

    /// What is the `Item` of the output `ParallelIterator`?
    type Item: Send;

    /// Convert this type to a `ParallelIterator`.
    fn as_parallel(self) -> Self::Iter;
}

impl<T: Iterator + Send> AsParallel for T
    where T::Item: Send
{
    type Iter = IterParallel<T>;
    type Item = T::Item;

    fn as_parallel(self) -> Self::Iter {
        IterParallel {
            iter: self,
        }
    }
}

/// `IterParallel` is a parallel iterator that wraps a sequential iterator.
#[derive(Debug)]
pub struct IterParallel<Iter> {
    iter: Iter,
}

impl<Iter: Iterator + Send> ParallelIterator for IterParallel<Iter>
    where Iter::Item: Send
{
    type Item = Iter::Item;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let split_count = AtomicUsize::new(current_num_threads());
        let deque = Deque::new();
        let stealer = deque.stealer();
        let done = AtomicBool::new(false);
        let iter = Mutex::new((self.iter, deque));

        bridge_unindexed(IterParallelProducer {
            split_count: &split_count,
            done: &done,
            iter: &iter,
            items: stealer,
        }, consumer)
    }
}

struct IterParallelProducer<'a, Iter: Iterator + 'a> {
    split_count: &'a AtomicUsize,
    done: &'a AtomicBool,
    iter: &'a Mutex<(Iter, Deque<Iter::Item>)>,
    items: Stealer<Iter::Item>,
}

// manual clone because T doesn't need to be Clone, but the derive assumes it should be
impl<'a, Iter: Iterator + 'a> Clone for IterParallelProducer<'a, Iter> {
    fn clone(&self) -> Self {
        IterParallelProducer {
            split_count: self.split_count,
            done: self.done,
            iter: self.iter,
            items: self.items.clone(),
        }
    }
}

impl<'a, Iter: Iterator + Send + 'a> UnindexedProducer for IterParallelProducer<'a, Iter>
    where Iter::Item: Send
{
    type Item = Iter::Item;

    fn split(self) -> (Self, Option<Self>) {
        let mut count = self.split_count.load(Ordering::SeqCst);

        loop {
            let done = self.done.load(Ordering::SeqCst);
            match count.checked_sub(1) {
                Some(new_count) if !done => {
                    let last_count = self.split_count.compare_and_swap(count, new_count, Ordering::SeqCst);
                    if last_count == count {
                        return (self.clone(), Some(self));
                    } else {
                        count = last_count;
                    }
                }
                _ => {
                    return (self, None);
                }
            }
        }
    }

    fn fold_with<F>(self, mut folder: F) -> F
        where F: Folder<Self::Item>
    {
        loop {
            match self.items.steal() {
                Steal::Data(it) => {
                    folder = folder.consume(it);
                    if folder.full() {
                        return folder;
                    }
                }
                Steal::Empty => {
                    if self.done.load(Ordering::SeqCst) {
                        // the iterator is out of items, no use in continuing
                        return folder;
                    } else {
                        // our cache is out of items, time to load more from the iterator
                        match self.iter.try_lock() {
                            Ok(mut guard) => {
                                let count = current_num_threads();
                                let count = (count * count) * 2;

                                let (ref mut iter, ref deque) = *guard;

                                for _ in 0..count {
                                    if let Some(it) = iter.next() {
                                        deque.push(it);
                                    } else {
                                        self.done.store(true, Ordering::SeqCst);
                                        break;
                                    }
                                }
                            }
                            Err(TryLockError::WouldBlock) => {
                                // someone else has the mutex, just sit tight until it's ready
                                yield_now(); //TODO: use a thread=pool-aware yield? (#548)
                            }
                            Err(TryLockError::Poisoned(_)) => {
                                // TODO: how to handle poison?
                                return folder;
                            }
                        }
                    }
                }
                Steal::Retry => (),
            }
        }
    }
}
<commit_msg>fix imports<commit_after>use crossbeam_deque::{Deque, Stealer, Steal};

use std::thread::yield_now;
use std::sync::{Mutex, TryLockError};
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering};

use iter::ParallelIterator;
use iter::plumbing::{UnindexedConsumer, UnindexedProducer, bridge_unindexed, Folder};
use current_num_threads;

/// Conversion trait to convert an `Iterator` to a `ParallelIterator`.
///
/// This needs to be distinct from `IntoParallelIterator` because that trait is already implemented
/// on a few `Iterator`s, like `std::ops::Range`.
pub trait AsParallel {
    /// What is the type of the output `ParallelIterator`?
    type Iter: ParallelIterator<Item = Self::Item>;

    /// What is the `Item` of the output `ParallelIterator`?
    type Item: Send;

    /// Convert this type to a `ParallelIterator`.
    fn as_parallel(self) -> Self::Iter;
}

impl<T: Iterator + Send> AsParallel for T
    where T::Item: Send
{
    type Iter = IterParallel<T>;
    type Item = T::Item;

    fn as_parallel(self) -> Self::Iter {
        IterParallel {
            iter: self,
        }
    }
}

/// `IterParallel` is a parallel iterator that wraps a sequential iterator.
#[derive(Debug)]
pub struct IterParallel<Iter> {
    iter: Iter,
}

impl<Iter: Iterator + Send> ParallelIterator for IterParallel<Iter>
    where Iter::Item: Send
{
    type Item = Iter::Item;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let split_count = AtomicUsize::new(current_num_threads());
        let deque = Deque::new();
        let stealer = deque.stealer();
        let done = AtomicBool::new(false);
        let iter = Mutex::new((self.iter, deque));

        bridge_unindexed(IterParallelProducer {
            split_count: &split_count,
            done: &done,
            iter: &iter,
            items: stealer,
        }, consumer)
    }
}

struct IterParallelProducer<'a, Iter: Iterator + 'a> {
    split_count: &'a AtomicUsize,
    done: &'a AtomicBool,
    iter: &'a Mutex<(Iter, Deque<Iter::Item>)>,
    items: Stealer<Iter::Item>,
}

// manual clone because T doesn't need to be Clone, but the derive assumes it should be
impl<'a, Iter: Iterator + 'a> Clone for IterParallelProducer<'a, Iter> {
    fn clone(&self) -> Self {
        IterParallelProducer {
            split_count: self.split_count,
            done: self.done,
            iter: self.iter,
            items: self.items.clone(),
        }
    }
}

impl<'a, Iter: Iterator + Send + 'a> UnindexedProducer for IterParallelProducer<'a, Iter>
    where Iter::Item: Send
{
    type Item = Iter::Item;

    fn split(self) -> (Self, Option<Self>) {
        let mut count = self.split_count.load(Ordering::SeqCst);

        loop {
            let done = self.done.load(Ordering::SeqCst);
            match count.checked_sub(1) {
                Some(new_count) if !done => {
                    let last_count = self.split_count.compare_and_swap(count, new_count, Ordering::SeqCst);
                    if last_count == count {
                        return (self.clone(), Some(self));
                    } else {
                        count = last_count;
                    }
                }
                _ => {
                    return (self, None);
                }
            }
        }
    }

    fn fold_with<F>(self, mut folder: F) -> F
        where F: Folder<Self::Item>
    {
        loop {
            match self.items.steal() {
                Steal::Data(it) => {
                    folder = folder.consume(it);
                    if folder.full() {
                        return folder;
                    }
                }
                Steal::Empty => {
                    if self.done.load(Ordering::SeqCst) {
                        // the iterator is out of items, no use in continuing
                        return folder;
                    } else {
                        // our cache is out of items, time to load more from the iterator
                        match self.iter.try_lock() {
                            Ok(mut guard) => {
                                let count = current_num_threads();
                                let count = (count * count) * 2;

                                let (ref mut iter, ref deque) = *guard;

                                for _ in 0..count {
                                    if let Some(it) = iter.next() {
                                        deque.push(it);
                                    } else {
                                        self.done.store(true, Ordering::SeqCst);
                                        break;
                                    }
                                }
                            }
                            Err(TryLockError::WouldBlock) => {
                                // someone else has the mutex, just sit tight until it's ready
                                yield_now(); //TODO: use a thread=pool-aware yield? (#548)
                            }
                            Err(TryLockError::Poisoned(_)) => {
                                // TODO: how to handle poison?
                                return folder;
                            }
                        }
                    }
                }
                Steal::Retry => (),
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn sgels_(trans: c_char, m: CLPK_integer, n: *const CLPK_integer,
            nrhs: *const CLPK_integer, a: *mut CLPK_real, lda: *const CLPK_integer,
            b: *mut CLPK_real, ldb: *const CLPK_integer, work: CLPK_real,
            lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dgels_(trans: c_char, m: CLPK_integer, n: *const CLPK_integer,
            nrhs: *const CLPK_integer, a: *mut CLPK_doublereal, lda: *const CLPK_integer,
            b: *mut CLPK_doublereal, ldb: *const CLPK_integer,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn cgels_(trans: c_char, m: CLPK_integer, n: *const CLPK_integer,
            nrhs: *const CLPK_integer, a: *mut CLPK_complex, lda: *const CLPK_integer,
            b: *mut CLPK_complex, ldb: *const CLPK_integer, work: CLPK_complex,
            lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn zgels_(trans: c_char, m: CLPK_integer, n: *const CLPK_integer,
            nrhs: *const CLPK_integer, a: *mut CLPK_doublecomplex,
            lda: *const CLPK_integer, b: *mut CLPK_doublecomplex, ldb: *const CLPK_integer,
            work: CLPK_doublecomplex, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
}
<commit_msg>Add Gglse trait<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn sgels_(trans: c_char, m: CLPK_integer, n: *const CLPK_integer,
            nrhs: *const CLPK_integer, a: *mut CLPK_real, lda: *const CLPK_integer,
            b: *mut CLPK_real, ldb: *const CLPK_integer, work: CLPK_real,
            lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dgels_(trans: c_char, m: CLPK_integer, n: *const CLPK_integer,
            nrhs: *const CLPK_integer, a: *mut CLPK_doublereal, lda: *const CLPK_integer,
            b: *mut CLPK_doublereal, ldb: *const CLPK_integer,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn cgels_(trans: c_char, m: CLPK_integer, n: *const CLPK_integer,
            nrhs: *const CLPK_integer, a: *mut CLPK_complex, lda: *const CLPK_integer,
            b: *mut CLPK_complex, ldb: *const CLPK_integer, work: CLPK_complex,
            lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn zgels_(trans: c_char, m: CLPK_integer, n: *const CLPK_integer,
            nrhs: *const CLPK_integer, a: *mut CLPK_doublecomplex,
            lda: *const CLPK_integer, b: *mut CLPK_doublecomplex, ldb: *const CLPK_integer,
            work: CLPK_doublecomplex, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;

    pub fn sgglse_(m: CLPK_integer, n: *const CLPK_integer, p: CLPK_integer,
            a: *mut CLPK_real, lda: *const CLPK_integer, b: *mut CLPK_real,
            ldb: *const CLPK_integer, c: CLPK_real, d: CLPK_real,
            x: CLPK_real, work: CLPK_real, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dgglse_(m: CLPK_integer, n: *const CLPK_integer, p: CLPK_integer,
            a: *mut CLPK_doublereal, lda: *const CLPK_integer, b: *mut CLPK_doublereal,
            ldb: *const CLPK_integer, c: CLPK_doublereal,
            d: CLPK_doublereal, x: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn cgglse_(m: CLPK_integer, n: *const CLPK_integer, p: CLPK_integer,
            a: *mut CLPK_complex, lda: *const CLPK_integer, b: *mut CLPK_complex,
            ldb: *const CLPK_integer, c: CLPK_complex, d: CLPK_complex,
            x: CLPK_complex, work: CLPK_complex, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn zgglse_(m: CLPK_integer, n: *const CLPK_integer, p: CLPK_integer,
            a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            b: *mut CLPK_doublecomplex, ldb: *const CLPK_integer,
            c: CLPK_doublecomplex, d: CLPK_doublecomplex,
            x: CLPK_doublecomplex, work: CLPK_doublecomplex,
            lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! Implementation of ElasticSearch Mapping operation

use std::collections::HashMap;

use ::Client;
use ::error::EsError;

pub type Properties = HashMap<String, HashMap<String, String>>;

/// An indexing operation
pub struct MappingOperation<'a, 'b> {
    /// The HTTP client that this operation will use
    client:     &'a mut Client,

    /// The index that will be created and eventually mapped
    index:      &'b str,

    /// The actual mapping
    properties: &'b Properties
}

impl<'a, 'b> MappingOperation<'a, 'b> {
    pub fn new(client: &'a mut Client, index: &'b str, properties: &'b Properties) -> MappingOperation<'a, 'b> {
        MappingOperation {
            client:     client,
            index:      index,
            properties: properties
        }
    }

    pub fn send(&'b mut self) -> Result<MappingResult, EsError> {
        let body = hashmap! {
            "mappings" => hashmap! {
                "sample" => hashmap! {
                    "properties" => self.properties
                }
            }
        };

        let url = format!("{}", self.index);
        let (_, _) = try!(self.client.put_body_op(&url, &body));
        Ok(MappingResult)
    }
}

/// The result of a mapping operation
#[derive(Debug)]
pub struct MappingResult;

#[cfg(test)]
pub mod tests {
    extern crate env_logger;

    use std::collections::HashMap;

    use super::MappingOperation;

    #[test]
    fn test_mapping() {
        let index_name = "tests_test_mapping";
        let mut client = ::tests::make_client();

        client.delete_op(&format!("/{}", index_name)).unwrap();

        let mapping = hashmap! {
            "created_at".to_owned() => hashmap! {
                "type".to_owned() => "date".to_owned(),
                "format".to_owned() => "epoch_second".to_owned()
            },

            "title".to_owned() => hashmap! {
                "type".to_owned() => "string".to_owned(),
                "index".to_owned() => "not_analyzed".to_owned()
            }
        };

        let result = MappingOperation::new(&mut client, index_name, &mapping).send();
        assert!(result.is_ok());
    }
}
<commit_msg>Add warning to mapping implementation for future changes<commit_after>/*
 * Copyright 2016 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! Implementation of ElasticSearch Mapping operation
//!
//! Please note: this will grow and become a full implementation of the ElasticSearch
//! [Indices API](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices.html)
//! so subtle (potentially breaking) changes will be made to the API when that happens

use std::collections::HashMap;

use ::Client;
use ::error::EsError;

pub type Properties = HashMap<String, HashMap<String, String>>;

/// An indexing operation
pub struct MappingOperation<'a, 'b> {
    /// The HTTP client that this operation will use
    client:     &'a mut Client,

    /// The index that will be created and eventually mapped
    index:      &'b str,

    /// The actual mapping
    properties: &'b Properties
}

impl<'a, 'b> MappingOperation<'a, 'b> {
    pub fn new(client: &'a mut Client, index: &'b str, properties: &'b Properties) -> MappingOperation<'a, 'b> {
        MappingOperation {
            client:     client,
            index:      index,
            properties: properties
        }
    }

    pub fn send(&'b mut self) -> Result<MappingResult, EsError> {
        let body = hashmap! {
            "mappings" => hashmap! {
                "sample" => hashmap! {
                    "properties" => self.properties
                }
            }
        };

        let url = format!("{}", self.index);
        let (_, _) = try!(self.client.put_body_op(&url, &body));
        Ok(MappingResult)
    }
}

/// The result of a mapping operation
#[derive(Debug)]
pub struct MappingResult;

#[cfg(test)]
pub mod tests {
    extern crate env_logger;

    use std::collections::HashMap;

    use super::MappingOperation;

    #[test]
    fn test_mapping() {
        let index_name = "tests_test_mapping";
        let mut client = ::tests::make_client();

        client.delete_op(&format!("/{}", index_name)).unwrap();

        let mapping = hashmap! {
            "created_at".to_owned() => hashmap! {
                "type".to_owned() => "date".to_owned(),
                "format".to_owned() => "epoch_second".to_owned()
            },

            "title".to_owned() => hashmap! {
                "type".to_owned() => "string".to_owned(),
                "index".to_owned() => "not_analyzed".to_owned()
            }
        };

        let result = MappingOperation::new(&mut client, index_name, &mapping).send();
        assert!(result.is_ok());
    }
}
<|endoftext|>