<commit_before>#[macro_use]
extern crate serde_derive;
extern crate serde_xml_rs;

#[derive(Debug, Deserialize, Default)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize, Default)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

#[derive(Debug, Deserialize, Default)]
pub struct Inertial {
    #[serde(default)]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Geometry {
    Box { size: String },
    Cylinder { radius: f64, length: f64 },
    Sphere { radius: f64 },
    Mesh { filename: String, scale: f64 },
}

impl Default for Geometry {
    fn default() -> Geometry {
        Geometry::Box { size: "0 0 0".to_string() }
    }
}

#[derive(Debug, Deserialize)]
pub struct Color {
    pub rgba: String,
}

impl Default for Color {
    fn default() -> Color {
        Color { rgba: "0 0 0 0".to_string() }
    }
}

#[derive(Debug, Deserialize)]
pub struct Texture {
    pub filename: String,
}

impl Default for Texture {
    fn default() -> Texture {
        Texture { filename: "".to_string() }
    }
}

#[derive(Debug, Deserialize, Default)]
pub struct Material {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub color: Color,
    #[serde(default)]
    pub texture: Texture,
}

#[derive(Debug, Deserialize, Default)]
pub struct Visual {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
    #[serde(default)]
    pub material: Material,
}

#[derive(Debug, Deserialize, Default)]
pub struct Collision {
    #[serde(default)]
    pub name: String,
    pub origin: Pose,
    pub geometry: Geometry,
}

#[derive(Debug, Deserialize)]
pub struct Link {
    pub name: String,
    #[serde(default)]
    pub inertial: Inertial,
    #[serde(default)]
    pub visual: Visual,
    #[serde(default)]
    pub collision: Collision,
}

#[derive(Debug, Deserialize)]
pub struct Axis {
    pub xyz: String,
}

fn parse_array_from_string(string: &str) -> [f64; 3] {
    let vec = string.split(" ").filter_map(|x| x.parse::<f64>().ok()).collect::<Vec<_>>();
    assert!(vec.len() == 3);
    let mut arr = [0.0f64; 3];
    for i in 0..3 {
        arr[i] = vec[i];
    }
    arr
}

impl Axis {
    pub fn xyz_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.xyz)
    }
}

impl Default for Axis {
    fn default() -> Axis {
        Axis { xyz: "1 0 0".to_string() }
    }
}

#[derive(Debug, Deserialize)]
pub struct Pose {
    #[serde(default)]
    pub xyz: String,
    #[serde(default)]
    pub rpy: String,
}

impl Pose {
    pub fn xyz_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.xyz)
    }
    pub fn rpy_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.rpy)
    }
}

impl Default for Pose {
    fn default() -> Pose {
        Pose {
            xyz: "0 0 0".to_string(),
            rpy: "0 0 0".to_string(),
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum JointType {
    Revolute,
    Continuous,
    Prismatic,
    Fixed,
    Floating,
    Planar,
}

#[derive(Debug, Deserialize)]
pub struct JointLimit {
    #[serde(default)]
    pub lower: f64,
    #[serde(default)]
    pub upper: f64,
    pub effort: f64,
    pub velocity: f64,
}

#[derive(Debug, Deserialize, Default)]
pub struct Mimic {
    joint: String,
    multiplier: f64,
    offset: f64,
}

#[derive(Debug, Deserialize, Default)]
pub struct SafetyController {
    soft_lower_limit: f64,
    soft_upper_limit: f64,
    k_position: f64,
    k_velocity: f64,
}

#[derive(Debug, Deserialize)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: String,
    #[serde(default)]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default)]
    pub axis: Axis,
    pub limit: JointLimit,
    #[serde(default)]
    pub dynamics: Dynamics,
    #[serde(default)]
    pub mimic: Mimic,
    #[serde(default)]
    pub safety_controller: SafetyController,
}

#[derive(Debug, Deserialize, Default)]
pub struct Dynamics {
    damping: f64,
    friction: f64,
}

#[derive(Debug, Deserialize)]
pub struct Robot {
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,
}

pub fn deserialize(string: &str) -> Result<Robot, serde_xml_rs::Error> {
    serde_xml_rs::deserialize(string.as_bytes())
}

#[test]
fn it_works() {
    let s = r##"
        <robot name="robo">
            <link name="shoulder1">
                <inertial>
                    <origin xyz="0 0 0.5" rpy="0 0 0"/>
                    <mass value="1"/>
                    <inertia ixx="100"  ixy="0"  ixz="0" iyy="100" iyz="0" izz="100" />
                </inertial>
                <visual>
                    <origin xyz="0.1 0.2 0.3" rpy="-0.1 -0.2  -0.3" />
                    <geometry>
                        <box size="1 1 1" />
                    </geometry>
                    <material name="Cyan">
                        <color rgba="0 1.0 1.0 1.0"/>
                    </material>
                </visual>
                <collision>
                    <origin xyz="0 0 0" rpy="0 0 0"/>
                    <geometry>
                        <cylinder radius="1" length="0.5"/>
                    </geometry>
                </collision>
            </link>
            <link name="elbow1" />
            <link name="wrist1" />
            <joint name="shoulder_pitch" type="revolute">
                <origin xyz="0.0 0.0 0.1" />
                <parent link="shoulder1" />
                <child link="elbow1" />
                <axis xyz="0 1 -1" />
                <limit lower="-1" upper="1.0" effort="0" velocity="1.0"/>
            </joint>
            <joint name="shoulder_pitch" type="revolute">
                <origin xyz="0.0, 0.0, 0.0" />
                <parent link="elbow1" />
                <child link="wrist1" />
                <axis xyz="0 1 0" />
                <limit lower="-2" upper="1.0" effort="0" velocity="1.0"/>
            </joint>
        </robot>
    "##;
    let robo = deserialize(s).unwrap();

    assert_eq!(robo.name, "robo");
    assert_eq!(robo.links.len(), 3);
    assert_eq!(robo.joints.len(), 2);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[0], 0.1);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[1], 0.2);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[2], 0.3);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[0], -0.1);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[1], -0.2);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[2], -0.3);

    assert_eq!(robo.joints[0].name, "shoulder_pitch");
    assert_eq!(robo.joints[0].axis.xyz, "0 1 -1");
    assert_eq!(robo.joints[0].axis.xyz_as_array()[0], 0.0f64);
    assert_eq!(robo.joints[0].axis.xyz_as_array()[1], 1.0f64);
    assert_eq!(robo.joints[0].axis.xyz_as_array()[2], -1.0f64);
    assert_eq!(robo.joints[0].origin.xyz, "0.0 0.0 0.1");
}
<commit_msg>Support file read in urdf-rs<commit_after>#[macro_use]
extern crate serde_derive;
extern crate serde_xml_rs;

#[derive(Debug, Deserialize, Default)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize, Default)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

#[derive(Debug, Deserialize, Default)]
pub struct Inertial {
    #[serde(default)]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Geometry {
    Box { size: String },
    Cylinder { radius: f64, length: f64 },
    Sphere { radius: f64 },
    Mesh { filename: String, scale: f64 },
}

impl Default for Geometry {
    fn default() -> Geometry {
        Geometry::Box { size: "0 0 0".to_string() }
    }
}

#[derive(Debug, Deserialize)]
pub struct Color {
    pub rgba: String,
}

impl Default for Color {
    fn default() -> Color {
        Color { rgba: "0 0 0 0".to_string() }
    }
}

#[derive(Debug, Deserialize)]
pub struct Texture {
    pub filename: String,
}

impl Default for Texture {
    fn default() -> Texture {
        Texture { filename: "".to_string() }
    }
}

#[derive(Debug, Deserialize, Default)]
pub struct Material {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub color: Color,
    #[serde(default)]
    pub texture: Texture,
}

#[derive(Debug, Deserialize, Default)]
pub struct Visual {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
    #[serde(default)]
    pub material: Material,
}

#[derive(Debug, Deserialize, Default)]
pub struct Collision {
    #[serde(default)]
    pub name: String,
    pub origin: Pose,
    pub geometry: Geometry,
}

#[derive(Debug, Deserialize)]
pub struct Link {
    pub name: String,
    #[serde(default)]
    pub inertial: Inertial,
    #[serde(default)]
    pub visual: Visual,
    #[serde(default)]
    pub collision: Collision,
}

#[derive(Debug, Deserialize)]
pub struct Axis {
    pub xyz: String,
}

fn parse_array_from_string(string: &str) -> [f64; 3] {
    let vec = string.split(" ").filter_map(|x| x.parse::<f64>().ok()).collect::<Vec<_>>();
    assert!(vec.len() == 3);
    let mut arr = [0.0f64; 3];
    for i in 0..3 {
        arr[i] = vec[i];
    }
    arr
}

impl Axis {
    pub fn xyz_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.xyz)
    }
}

impl Default for Axis {
    fn default() -> Axis {
        Axis { xyz: "1 0 0".to_string() }
    }
}

#[derive(Debug, Deserialize)]
pub struct Pose {
    #[serde(default)]
    pub xyz: String,
    #[serde(default)]
    pub rpy: String,
}

impl Pose {
    pub fn xyz_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.xyz)
    }
    pub fn rpy_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.rpy)
    }
}

impl Default for Pose {
    fn default() -> Pose {
        Pose {
            xyz: "0 0 0".to_string(),
            rpy: "0 0 0".to_string(),
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum JointType {
    Revolute,
    Continuous,
    Prismatic,
    Fixed,
    Floating,
    Planar,
}

#[derive(Debug, Deserialize)]
pub struct JointLimit {
    #[serde(default)]
    pub lower: f64,
    #[serde(default)]
    pub upper: f64,
    pub effort: f64,
    pub velocity: f64,
}

#[derive(Debug, Deserialize, Default)]
pub struct Mimic {
    joint: String,
    multiplier: f64,
    offset: f64,
}

#[derive(Debug, Deserialize, Default)]
pub struct SafetyController {
    soft_lower_limit: f64,
    soft_upper_limit: f64,
    k_position: f64,
    k_velocity: f64,
}

#[derive(Debug, Deserialize)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: JointType,
    #[serde(default)]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default)]
    pub axis: Axis,
    pub limit: JointLimit,
    #[serde(default)]
    pub dynamics: Dynamics,
    #[serde(default)]
    pub mimic: Mimic,
    #[serde(default)]
    pub safety_controller: SafetyController,
}

#[derive(Debug, Deserialize, Default)]
pub struct Dynamics {
    damping: f64,
    friction: f64,
}

#[derive(Debug, Deserialize)]
pub struct Robot {
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,
}

use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::error::Error;
use std::fmt;

#[derive(Debug)]
pub enum UrdfError {
    File(std::io::Error),
    Xml(serde_xml_rs::Error),
}

impl fmt::Display for UrdfError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            UrdfError::File(ref err) => err.fmt(f),
            UrdfError::Xml(ref err) => err.fmt(f),
        }
    }
}

impl Error for UrdfError {
    fn description(&self) -> &str {
        match *self {
            UrdfError::File(ref err) => err.description(),
            UrdfError::Xml(ref err) => err.description(),
        }
    }
}

impl From<std::io::Error> for UrdfError {
    fn from(err: std::io::Error) -> UrdfError {
        UrdfError::File(err)
    }
}

impl From<serde_xml_rs::Error> for UrdfError {
    fn from(err: serde_xml_rs::Error) -> UrdfError {
        UrdfError::Xml(err)
    }
}

pub fn read_file<P: AsRef<Path>>(path: P) -> Result<Robot, UrdfError> {
    let mut file = File::open(path)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    read_from_string(&contents)
}

pub fn read_from_string(string: &str) -> Result<Robot, UrdfError> {
    serde_xml_rs::deserialize(string.as_bytes())
        .map_err(From::from)
}

#[test]
fn it_works() {
    let s = r##"
        <robot name="robo">
            <link name="shoulder1">
                <inertial>
                    <origin xyz="0 0 0.5" rpy="0 0 0"/>
                    <mass value="1"/>
                    <inertia ixx="100"  ixy="0"  ixz="0" iyy="100" iyz="0" izz="100" />
                </inertial>
                <visual>
                    <origin xyz="0.1 0.2 0.3" rpy="-0.1 -0.2  -0.3" />
                    <geometry>
                        <box size="1 1 1" />
                    </geometry>
                    <material name="Cyan">
                        <color rgba="0 1.0 1.0 1.0"/>
                    </material>
                </visual>
                <collision>
                    <origin xyz="0 0 0" rpy="0 0 0"/>
                    <geometry>
                        <cylinder radius="1" length="0.5"/>
                    </geometry>
                </collision>
            </link>
            <link name="elbow1" />
            <link name="wrist1" />
            <joint name="shoulder_pitch" type="revolute">
                <origin xyz="0.0 0.0 0.1" />
                <parent link="shoulder1" />
                <child link="elbow1" />
                <axis xyz="0 1 -1" />
                <limit lower="-1" upper="1.0" effort="0" velocity="1.0"/>
            </joint>
            <joint name="shoulder_pitch" type="revolute">
                <origin xyz="0.0, 0.0, 0.0" />
                <parent link="elbow1" />
                <child link="wrist1" />
                <axis xyz="0 1 0" />
                <limit lower="-2" upper="1.0" effort="0" velocity="1.0"/>
            </joint>
        </robot>
    "##;
    let robo = read_from_string(s).unwrap();

    assert_eq!(robo.name, "robo");
    assert_eq!(robo.links.len(), 3);
    assert_eq!(robo.joints.len(), 2);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[0], 0.1);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[1], 0.2);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[2], 0.3);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[0], -0.1);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[1], -0.2);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[2], -0.3);

    assert_eq!(robo.joints[0].name, "shoulder_pitch");
    assert_eq!(robo.joints[0].axis.xyz, "0 1 -1");
    assert_eq!(robo.joints[0].axis.xyz_as_array()[0], 0.0f64);
    assert_eq!(robo.joints[0].axis.xyz_as_array()[1], 1.0f64);
    assert_eq!(robo.joints[0].axis.xyz_as_array()[2], -1.0f64);
    assert_eq!(robo.joints[0].origin.xyz, "0.0 0.0 0.1");
}
<|endoftext|>


<commit_before>use ::kdtree::*;

enum PointsWereOnSide {
    Left,
    Right,
    Both,
}

struct PartitionPointHelper {
    points_were_on_side: PointsWereOnSide,
    midpoint_split_value: f64,
    index_of_splitter: usize,
}

fn partition_sliding_midpoint_helper<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoint_value: f64, partition_on_dimension: usize) -> PartitionPointHelper {
    let mut closest_index = 0;
    let mut closest_distance = (vec[0].dims()[partition_on_dimension] - midpoint_value).abs();

    const HAS_POINTS_ON_LEFT_SIDE: i32 = 0b01;
    const HAS_POINTS_ON_RIGHT_SIDE: i32 = 0b10;
    const HAS_POINTS_ON_BOTH_SIDES: i32 = HAS_POINTS_ON_RIGHT_SIDE | HAS_POINTS_ON_LEFT_SIDE;
    let mut has_points_on_sides = 0;

    for i in 0..vec.len() {
        let p = vec.get(i).unwrap();
        if p.dims()[partition_on_dimension] <= midpoint_value {
            has_points_on_sides |= HAS_POINTS_ON_LEFT_SIDE;
        } else {
            has_points_on_sides |= HAS_POINTS_ON_RIGHT_SIDE;
        }

        let dist = (p.dims()[partition_on_dimension] - midpoint_value).abs();

        if dist < closest_distance {
            closest_distance = dist;
            closest_index = i;
        }
    }

    if has_points_on_sides != HAS_POINTS_ON_BOTH_SIDES {
        return PartitionPointHelper {
            index_of_splitter: closest_index,
            midpoint_split_value: vec.get(closest_index).unwrap().dims()[partition_on_dimension],
            points_were_on_side: if has_points_on_sides == HAS_POINTS_ON_LEFT_SIDE { PointsWereOnSide::Left } else { PointsWereOnSide::Right }
        }
    }
    return PartitionPointHelper {
        index_of_splitter: closest_index,
        midpoint_split_value: midpoint_value,
        points_were_on_side: PointsWereOnSide::Both
    }
}

pub fn partition_sliding_midpoint<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoint_value: f64, partition_on_dimension: usize) -> (usize, f64) {
    let vec_len = vec.len();
    debug_assert!(vec[0].dims().len() > partition_on_dimension);
    debug_assert!(vec.len() > 1);

    let partition_point_data = partition_sliding_midpoint_helper(vec, midpoint_value, partition_on_dimension);

    match partition_point_data.points_were_on_side {
        PointsWereOnSide::Left => {
            vec.swap(partition_point_data.index_of_splitter, vec_len - 1);
            (vec_len - 1, partition_point_data.midpoint_split_value)
        },
        PointsWereOnSide::Right => {
            vec.swap(partition_point_data.index_of_splitter, 0);
            (0, partition_point_data.midpoint_split_value)
        }
        PointsWereOnSide::Both => {
            let index_of_splitting_point = partition_kdtree(vec, partition_point_data.index_of_splitter, partition_on_dimension);
            (index_of_splitting_point, partition_point_data.midpoint_split_value)
        }
    }
}

fn partition_kdtree<T: KdtreePointTrait>(vec: &mut Vec<T>, index_of_splitting_point: usize, partition_on_dimension: usize) -> usize {
    let pivot = vec[index_of_splitting_point].dims()[partition_on_dimension];
    let vec_len = vec.len();

    vec.swap(index_of_splitting_point, vec_len - 1);

    //using Lomuto variant of partition here, change it to hoare sometime?
    let mut store_index = 0;
    for left in 0..vec_len - 1 {
        if vec[left].dims()[partition_on_dimension] <= pivot {
            vec.swap(left, store_index);
            store_index += 1;
        }
    }

    vec.swap(store_index, vec_len - 1);

    store_index
}

#[cfg(test)]
mod tests {
    use ::kdtree::*;
    use ::kdtree::test_common::tests_utils::*;

    use ::rand::distributions::{IndependentSample, Range};
    use ::rand::*;

    use super::*;
    use super::partition_kdtree;

    #[test]
    fn parition_kdtree_works() {
        let p1 = Point2WithId::new(0, 1., 4.);
        let p2 = Point2WithId::new(1, 2., 6.);
        let p3 = Point2WithId::new(2, 3., 8.);
        let p4 = Point2WithId::new(3, 0., 8.);
        let p5 = Point2WithId::new(4, -1., 8.);
        let p6 = Point2WithId::new(5, 3., 8.);
        let p7 = Point2WithId::new(6, 4., 8.);

        let mut vec = vec![p1, p2, p3, p4, p5, p6, p7];
        assert_eq! (1, partition_kdtree(&mut vec.clone(), 3, 0));

        assert_eq! (6, partition_kdtree(&mut vec.clone(), 6, 0));

        assert_eq! (0, partition_kdtree(&mut vec.clone(), 4, 0));

        assert_eq! (5, partition_kdtree(&mut vec.clone(), 2, 0));
    }

    quickcheck! {
        fn partition_kdtree_qc(xs: Vec<f64>) -> bool {
            let mut vec : Vec<Point1WithId> = vec![];

            for i in 0 .. xs.len() {
                let p = Point1WithId::new(i as i32, xs[i]);
                vec.push(p);
            }

            if(xs.len() == 0 ) {
                return true;
            }
            let between = Range::new(0, xs.len());
            let mut rng = thread_rng();

            for i in 0 .. 5 {
                let random_splitting_index = between.ind_sample(&mut rng);

                let mut vec = vec.clone();

                let index_of_splitting_point = partition_kdtree(&mut vec, random_splitting_index, 0);
                return assert_partition(&vec, index_of_splitting_point);
            }

            true
        }
    }

    #[test]
    #[ignore]
    fn partition_given_midpoint_exactly_in_between_points_returns_smaller_index() {
        let p1 = Point2WithId::new(1, 2., 4.);
        let p2 = Point2WithId::new(1, 4., 6.);
        let mut vec = vec![p1, p2];

        assert_eq! ((0, 3.), partition_sliding_midpoint(&mut vec, 3., 0));
        assert_eq! ((0, 5.), partition_sliding_midpoint(&mut vec, 5., 1));
    }

    #[test]
    #[ignore]
    fn partition_given_midpoint_which_has_all_points_on_one_side_slides_split_plane_and_returns_index_to_closest_element() {
        let p1 = Point2WithId::new(1, 2., 4.);
        let p2 = Point2WithId::new(2, 4., 6.);
        let p3 = Point2WithId::new(3, 3., 7.);
        let p4 = Point2WithId::new(4, 0., 8.);
        let mut vec = vec![p1, p2, p3];

        assert_eq! ((0, 2.), partition_sliding_midpoint(&mut vec, 1.9, 0));
        assert_eq! (1, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);

        let mut vec = vec![p1, p2, p3];
        assert_eq! ((0, 2.), partition_sliding_midpoint(&mut vec, -5000., 0));
        assert_eq! (1, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);

        let mut vec = vec![p1, p2, p3];
        assert_eq! ((2, 4.), partition_sliding_midpoint(&mut vec, 10., 0));
        assert_eq! (1, vec[0].id);
        assert_eq! (3, vec[1].id);
        assert_eq! (2, vec[2].id);

        let mut vec = vec![p1, p2, p3];
        assert_eq! ((2, 7.), partition_sliding_midpoint(&mut vec, 10., 1));
        assert_eq! (1, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);

        let mut vec = vec![p1, p2, p3, p4];
        assert_eq! ((0, 0.), partition_sliding_midpoint(&mut vec, -5000., 0));
        assert_eq! (4, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);
        assert_eq! (1, vec[3].id);
    }

    fn assert_partition(v: &Vec<Point1WithId>, index_of_splitting_point: usize) -> bool {
        let pivot = v[index_of_splitting_point].dims()[0];

        for i in 0 .. index_of_splitting_point {
            if v[i].dims()[0] > pivot {
                return false;
            }
        }

        for i in index_of_splitting_point + 1 .. v.len() {
            if v[i].dims()[0] < pivot {
                return false;
            }
        }

        true
    }
}<commit_msg>Implemented lomuto instead of hoare, partition<commit_after>use ::kdtree::*;

enum PointsWereOnSide {
    Left,
    Right,
    Both,
}

struct PartitionPointHelper {
    points_were_on_side: PointsWereOnSide,
    midpoint_split_value: f64,
    index_of_splitter: usize,
}

fn partition_sliding_midpoint_helper<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoint_value: f64, partition_on_dimension: usize) -> PartitionPointHelper {
    let mut closest_index = 0;
    let mut closest_distance = (vec[0].dims()[partition_on_dimension] - midpoint_value).abs();

    const HAS_POINTS_ON_LEFT_SIDE: i32 = 0b01;
    const HAS_POINTS_ON_RIGHT_SIDE: i32 = 0b10;
    const HAS_POINTS_ON_BOTH_SIDES: i32 = HAS_POINTS_ON_RIGHT_SIDE | HAS_POINTS_ON_LEFT_SIDE;
    let mut has_points_on_sides = 0;

    for i in 0..vec.len() {
        let p = vec.get(i).unwrap();
        if p.dims()[partition_on_dimension] <= midpoint_value {
            has_points_on_sides |= HAS_POINTS_ON_LEFT_SIDE;
        } else {
            has_points_on_sides |= HAS_POINTS_ON_RIGHT_SIDE;
        }

        let dist = (p.dims()[partition_on_dimension] - midpoint_value).abs();

        if dist < closest_distance {
            closest_distance = dist;
            closest_index = i;
        }
    }

    if has_points_on_sides != HAS_POINTS_ON_BOTH_SIDES {
        return PartitionPointHelper {
            index_of_splitter: closest_index,
            midpoint_split_value: vec.get(closest_index).unwrap().dims()[partition_on_dimension],
            points_were_on_side: if has_points_on_sides == HAS_POINTS_ON_LEFT_SIDE { PointsWereOnSide::Left } else { PointsWereOnSide::Right }
        }
    }
    return PartitionPointHelper {
        index_of_splitter: closest_index,
        midpoint_split_value: midpoint_value,
        points_were_on_side: PointsWereOnSide::Both
    }
}

pub fn partition_sliding_midpoint<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoint_value: f64, partition_on_dimension: usize) -> (usize, f64) {
    let vec_len = vec.len();
    debug_assert!(vec[0].dims().len() > partition_on_dimension);
    debug_assert!(vec.len() > 1);

    let partition_point_data = partition_sliding_midpoint_helper(vec, midpoint_value, partition_on_dimension);

    match partition_point_data.points_were_on_side {
        PointsWereOnSide::Left => {
            vec.swap(partition_point_data.index_of_splitter, vec_len - 1);
            (vec_len - 1, partition_point_data.midpoint_split_value)
        },
        PointsWereOnSide::Right => {
            vec.swap(partition_point_data.index_of_splitter, 0);
            (0, partition_point_data.midpoint_split_value)
        }
        PointsWereOnSide::Both => {
            let index_of_splitting_point = partition_kdtree(vec, partition_point_data.index_of_splitter, partition_on_dimension);
            (index_of_splitting_point, partition_point_data.midpoint_split_value)
        }
    }
}

fn partition_kdtree<T: KdtreePointTrait>(vec: &mut Vec<T>, index_of_splitting_point: usize, partition_on_dimension: usize) -> usize {
    if vec.len() == 1 {
        return 0;
    }

    let pivot = vec[index_of_splitting_point].dims()[partition_on_dimension];
    let vec_len = vec.len();

    vec.swap(index_of_splitting_point, vec_len - 1);

    let mut left = 0usize;
    let mut right = vec.len() - 2;
    let mut last_succesful_swap = vec.len() -1;

    //variant of Lomuto algo.
    loop {
        while left <= right && vec[left].dims()[partition_on_dimension] <= pivot {
            left += 1;
        }

        while right > left && vec[right].dims()[partition_on_dimension] > pivot {
            right -= 1;
        }

        if right > left {
            vec.swap(left, right);
            last_succesful_swap = right;

            left += 1;
            right -= 1;

        } else {
            break;
        }
    }

    if last_succesful_swap == vec_len -1 && vec[right].dims()[partition_on_dimension] > pivot {
        vec.swap(right, last_succesful_swap);
        last_succesful_swap = right;
    } else if vec[left].dims()[partition_on_dimension] > pivot {
        vec.swap(left, vec_len -1);
        last_succesful_swap = left;
    } else {
        vec.swap(last_succesful_swap, vec_len - 1);
    }

    last_succesful_swap
}

#[cfg(test)]
mod tests {
    use ::kdtree::*;
    use ::kdtree::test_common::tests_utils::*;

    use ::rand::distributions::{IndependentSample, Range};
    use ::rand::*;

    use super::*;
    use super::partition_kdtree;

    #[test]
    fn parition_kdtree_works() {
        let p1 = Point2WithId::new(0, 1., 4.);
        let p2 = Point2WithId::new(1, 2., 6.);
        let p3 = Point2WithId::new(2, 3., 8.);
        let p4 = Point2WithId::new(3, 0., 8.);
        let p5 = Point2WithId::new(4, -1., 8.);
        let p6 = Point2WithId::new(5, 3., 8.);
        let p7 = Point2WithId::new(6, 4., 8.);

        let mut vec = vec![p1, p2, p3, p4, p5, p6, p7];
        assert_eq! (1, partition_kdtree(&mut vec.clone(), 3, 0));

        assert_eq! (6, partition_kdtree(&mut vec.clone(), 6, 0));

        assert_eq! (0, partition_kdtree(&mut vec.clone(), 4, 0));

        assert_eq! (5, partition_kdtree(&mut vec.clone(), 2, 0));
    }

    quickcheck! {
        fn partition_kdtree_qc(xs: Vec<f64>) -> bool {
            let mut vec : Vec<Point1WithId> = vec![];

            for i in 0 .. xs.len() {
                let p = Point1WithId::new(i as i32, xs[i]);
                vec.push(p);
            }

            if(xs.len() == 0 ) {
                return true;
            }
            let between = Range::new(0, xs.len());
            let mut rng = thread_rng();

            for i in 0 .. 5 {
                let random_splitting_index = between.ind_sample(&mut rng);

                let mut vec = vec.clone();

                let index_of_splitting_point = partition_kdtree(&mut vec, random_splitting_index, 0);
                return assert_partition(&vec, index_of_splitting_point);
            }

            true
        }
    }

    #[test]
    #[ignore]
    fn partition_given_midpoint_exactly_in_between_points_returns_smaller_index() {
        let p1 = Point2WithId::new(1, 2., 4.);
        let p2 = Point2WithId::new(1, 4., 6.);
        let mut vec = vec![p1, p2];

        assert_eq! ((0, 3.), partition_sliding_midpoint(&mut vec, 3., 0));
        assert_eq! ((0, 5.), partition_sliding_midpoint(&mut vec, 5., 1));
    }

    #[test]
    #[ignore]
    fn partition_given_midpoint_which_has_all_points_on_one_side_slides_split_plane_and_returns_index_to_closest_element() {
        let p1 = Point2WithId::new(1, 2., 4.);
        let p2 = Point2WithId::new(2, 4., 6.);
        let p3 = Point2WithId::new(3, 3., 7.);
        let p4 = Point2WithId::new(4, 0., 8.);
        let mut vec = vec![p1, p2, p3];

        assert_eq! ((0, 2.), partition_sliding_midpoint(&mut vec, 1.9, 0));
        assert_eq! (1, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);

        let mut vec = vec![p1, p2, p3];
        assert_eq! ((0, 2.), partition_sliding_midpoint(&mut vec, -5000., 0));
        assert_eq! (1, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);

        let mut vec = vec![p1, p2, p3];
        assert_eq! ((2, 4.), partition_sliding_midpoint(&mut vec, 10., 0));
        assert_eq! (1, vec[0].id);
        assert_eq! (3, vec[1].id);
        assert_eq! (2, vec[2].id);

        let mut vec = vec![p1, p2, p3];
        assert_eq! ((2, 7.), partition_sliding_midpoint(&mut vec, 10., 1));
        assert_eq! (1, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);

        let mut vec = vec![p1, p2, p3, p4];
        assert_eq! ((0, 0.), partition_sliding_midpoint(&mut vec, -5000., 0));
        assert_eq! (4, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);
        assert_eq! (1, vec[3].id);
    }

    fn assert_partition(v: &Vec<Point1WithId>, index_of_splitting_point: usize) -> bool {
        let pivot = v[index_of_splitting_point].dims()[0];

        for i in 0..index_of_splitting_point {
            if v[i].dims()[0] > pivot {
                return false;
            }
        }

        for i in index_of_splitting_point + 1..v.len() {
            if v[i].dims()[0] < pivot {
                return false;
            }
        }

        true
    }
}<|endoftext|>


<commit_before>#[doc = "

Handy functions for creating class objects and so forth.

"];

// Can't use spidermonkey::crust::* versions due to Rust #2440

import libc::c_uint;
export basic_class;
export global_class;
export debug_fns;

fn basic_class(np: name_pool, -name: ~str) -> JSClass {
    {name: np.add(name),
     flags: 0x48000_u32,
     addProperty: crust::JS_PropertyStub,
     delProperty: crust::JS_PropertyStub,
     getProperty: crust::JS_PropertyStub,
     setProperty: crust::JS_StrictPropertyStub,
     enumerate: crust::JS_EnumerateStub,
     resolve: crust::JS_ResolveStub,
     convert: crust::JS_ConvertStub,
     finalize: null(),
     checkAccess: null(),
     call: null(),
     construct: null(),
     hasInstance: null(),
     trace: null(),
     reserved: (null(), null(), null(), null(), null(),  // 05
                null(), null(), null(), null(), null(),  // 10
                null(), null(), null(), null(), null(),  // 15
                null(), null(), null(), null(), null(),  // 20
                null(), null(), null(), null(), null(),  // 25
                null(), null(), null(), null(), null(),  // 30
                null(), null(), null(), null(), null(),  // 35
                null(), null(), null(), null(), null())} // 40
}

fn global_class(np: name_pool) -> JSClass {
    basic_class(np, ~"global")
}

extern fn debug(cx: *JSContext, argc: c_uint, vp: *jsval) -> JSBool {
    import io::WriterUtil;

    unsafe {
        let argv = JS_ARGV(cx, vp);
        for uint::range(0u, argc as uint) |i| {
            let jsstr = JS_ValueToString(cx, *ptr::offset(argv, i));
            let bytes = JS_EncodeString(cx, jsstr);
            let str = str::unsafe::from_c_str(bytes);
            JS_free(cx, unsafe::reinterpret_cast(bytes));
            #debug["%s", str];
        }
        JS_SET_RVAL(cx, vp, JSVAL_NULL);
        return 1_i32;
    }
}

fn debug_fns(np: name_pool) -> ~[JSFunctionSpec] {
    ~[{name: np.add(~"debug"),
       call: debug,
       nargs: 0_u16,
       flags: 0_u16}]
}
<commit_msg>Factor string-munging code out of debug and export it<commit_after>#[doc = "

Handy functions for creating class objects and so forth.

"];

// Can't use spidermonkey::crust::* versions due to Rust #2440

import libc::c_uint;
export basic_class;
export global_class;
export debug_fns;
export jsval_to_rust_str;

fn basic_class(np: name_pool, -name: ~str) -> JSClass {
    {name: np.add(name),
     flags: 0x48000_u32,
     addProperty: crust::JS_PropertyStub,
     delProperty: crust::JS_PropertyStub,
     getProperty: crust::JS_PropertyStub,
     setProperty: crust::JS_StrictPropertyStub,
     enumerate: crust::JS_EnumerateStub,
     resolve: crust::JS_ResolveStub,
     convert: crust::JS_ConvertStub,
     finalize: null(),
     checkAccess: null(),
     call: null(),
     construct: null(),
     hasInstance: null(),
     trace: null(),
     reserved: (null(), null(), null(), null(), null(),  // 05
                null(), null(), null(), null(), null(),  // 10
                null(), null(), null(), null(), null(),  // 15
                null(), null(), null(), null(), null(),  // 20
                null(), null(), null(), null(), null(),  // 25
                null(), null(), null(), null(), null(),  // 30
                null(), null(), null(), null(), null(),  // 35
                null(), null(), null(), null(), null())} // 40
}

fn global_class(np: name_pool) -> JSClass {
    basic_class(np, ~"global")
}

unsafe fn jsval_to_rust_str(cx: *JSContext, vp: *jsapi::JSString) -> ~str {
  let bytes = JS_EncodeString(cx, vp);
  let s = str::unsafe::from_c_str(bytes);
  JS_free(cx, unsafe::reinterpret_cast(bytes));
  s
}

extern fn debug(cx: *JSContext, argc: c_uint, vp: *jsval) -> JSBool {
    import io::WriterUtil;

    unsafe {
        let argv = JS_ARGV(cx, vp);
        for uint::range(0u, argc as uint) |i| {
            let jsstr = JS_ValueToString(cx, *ptr::offset(argv, i));
            #debug["%s", jsval_to_rust_str(cx, jsstr)];
        }
        JS_SET_RVAL(cx, vp, JSVAL_NULL);
        return 1_i32;
    }
}

fn debug_fns(np: name_pool) -> ~[JSFunctionSpec] {
    ~[{name: np.add(~"debug"),
       call: debug,
       nargs: 0_u16,
       flags: 0_u16}]
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use rand;
use rand::Rng;
use rustc_serialize::json;
use super::ecs::{Ecs, Comps};
use super::area::Area;
use super::spatial::Spatial;
use super::flags::Flags;
use super::action;
use super::prototype;
use super::{Biome, AreaSpec};

thread_local!(static WORLD_STATE: RefCell<WorldState> = RefCell::new(WorldState::new(None)));

/// Access world state for reading. The world state may not be reaccessed for
/// writing while within this function.
pub fn with<A, F>(mut f: F) -> A
    where F: FnMut(&WorldState) -> A {
    WORLD_STATE.with(|w| f(& *w.borrow()))
}

/// Access world state for reading and writing. The world state may not be
/// reaccessed while within this function.
pub fn with_mut<A, F>(mut f: F) -> A
    where F: FnMut(&mut WorldState) -> A {
    WORLD_STATE.with(|w| f(&mut *w.borrow_mut()))
}

/// Save the global world state into a json string.
pub fn save() -> String {
    with(|w| json::encode(w).unwrap())
}

/// Load the global world state from a json string. If the load operation
/// is successful, the previous world state will be overwritten by the loaded
/// one.
pub fn load(json: &str) -> Result<(), json::DecoderError> {
    WORLD_STATE.with(|w| {
        match json::decode::<WorldState>(json) {
            Ok(ws) => {
                *w.borrow_mut() = ws;
                Ok(())
            }
            Err(e) => Err(e)
        }
    })
}

/// The internal object that holds all the world state data.
#[derive(RustcEncodable, RustcDecodable)]
pub struct WorldState {
    /// Global entity handler.
    pub ecs: Ecs,
    /// World terrain generation and storage.
    pub area: Area,
    /// Spatial index for game entities.
    pub spatial: Spatial,
    /// Global gamestate flags.
    pub flags: Flags,

    pub comps: Comps,
}

impl<'a> WorldState {
    pub fn new(seed: Option<u32>) -> WorldState {
        let seed = match seed {
            Some(s) => s,
            // Use system rng for seed if the user didn't provide one.
            None => rand::thread_rng().gen()
        };
        WorldState {
            ecs: Ecs::new(),
            area: Area::new(seed, AreaSpec::new(Biome::Overland, 1)),
            spatial: Spatial::new(),
            flags: Flags::new(seed),
            comps: Comps::new(),
        }
    }
}

/// Set up a fresh start-game world state with an optional fixed random number
/// generator seed. Calling init_world will cause any existing world state to
/// be discarded.
pub fn init_world(seed: Option<u32>) {
    WORLD_STATE.with(|w| *w.borrow_mut() = WorldState::new(seed));
    prototype::init();

    action::start_level(1);
}
<commit_msg>Work around crashy RNG seed 0<commit_after>use std::cell::RefCell;
use rand;
use rand::Rng;
use rustc_serialize::json;
use super::ecs::{Ecs, Comps};
use super::area::Area;
use super::spatial::Spatial;
use super::flags::Flags;
use super::action;
use super::prototype;
use super::{Biome, AreaSpec};

thread_local!(static WORLD_STATE: RefCell<WorldState> = RefCell::new(WorldState::new(None)));

/// Access world state for reading. The world state may not be reaccessed for
/// writing while within this function.
pub fn with<A, F>(mut f: F) -> A
    where F: FnMut(&WorldState) -> A {
    WORLD_STATE.with(|w| f(& *w.borrow()))
}

/// Access world state for reading and writing. The world state may not be
/// reaccessed while within this function.
pub fn with_mut<A, F>(mut f: F) -> A
    where F: FnMut(&mut WorldState) -> A {
    WORLD_STATE.with(|w| f(&mut *w.borrow_mut()))
}

/// Save the global world state into a json string.
pub fn save() -> String {
    with(|w| json::encode(w).unwrap())
}

/// Load the global world state from a json string. If the load operation
/// is successful, the previous world state will be overwritten by the loaded
/// one.
pub fn load(json: &str) -> Result<(), json::DecoderError> {
    WORLD_STATE.with(|w| {
        match json::decode::<WorldState>(json) {
            Ok(ws) => {
                *w.borrow_mut() = ws;
                Ok(())
            }
            Err(e) => Err(e)
        }
    })
}

/// The internal object that holds all the world state data.
#[derive(RustcEncodable, RustcDecodable)]
pub struct WorldState {
    /// Global entity handler.
    pub ecs: Ecs,
    /// World terrain generation and storage.
    pub area: Area,
    /// Spatial index for game entities.
    pub spatial: Spatial,
    /// Global gamestate flags.
    pub flags: Flags,

    pub comps: Comps,
}

impl<'a> WorldState {
    pub fn new(seed: Option<u32>) -> WorldState {
        let seed = match seed {
            // Some RNGs don't like 0 as seed, work around this.
            Some(0) => 1,
            Some(s) => s,
            // Use system rng for seed if the user didn't provide one.
            None => rand::thread_rng().gen()
        };
        WorldState {
            ecs: Ecs::new(),
            area: Area::new(seed, AreaSpec::new(Biome::Overland, 1)),
            spatial: Spatial::new(),
            flags: Flags::new(seed),
            comps: Comps::new(),
        }
    }
}

/// Set up a fresh start-game world state with an optional fixed random number
/// generator seed. Calling init_world will cause any existing world state to
/// be discarded.
pub fn init_world(seed: Option<u32>) {
    WORLD_STATE.with(|w| *w.borrow_mut() = WorldState::new(seed));
    prototype::init();

    action::start_level(1);
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use ir::{BinaryOp, Block, BlockEnd, Function, Instruction, Program, Reg, Size, Symbol, UnaryOp,
         Value};

struct Context<'a> {
    functions: &'a HashMap<Symbol, Function>,
    function: &'a Function,
}

impl<'a> Context<'a> {
    fn new(program: &'a Program, function: &'a Function) -> Self {
        Context {
            functions: &program.functions,
            function,
        }
    }

    fn validate(&self) {
        if let Some(layout) = self.function.output_layout {
            assert!(layout.size > 0);
        }
        for &layout in self.function.registers.values() {
            assert!(layout.size > 0);
        }
        for &reg in &self.function.parameters {
            assert!(self.function.registers.contains_key(&reg));
        }
        if let Some(block) = self.function.start_block {
            assert!(self.function.blocks.contains_key(&block));
        }
        for block in self.function.blocks.values() {
            self.validate_block(block);
        }
    }

    fn validate_block(&self, block: &Block) {
        for op in &block.ops {
            self.validate_instruction(op);
        }
        match block.end {
            BlockEnd::Branch(ref val, a, b) => {
                assert_eq!(self.value_size(val), 1);
                assert!(self.function.blocks.contains_key(&a));
                assert!(self.function.blocks.contains_key(&b));
            }
            BlockEnd::Jump(block) => {
                assert!(self.function.blocks.contains_key(&block));
            }
            BlockEnd::Return(ref val) => {
                let return_size = self.function.output_layout.unwrap().size;
                assert_eq!(self.value_size(val), return_size);
            }
            BlockEnd::ReturnProc => {
                assert!(self.function.output_layout.is_none());
            }
        }
    }

    fn validate_instruction(&self, i: &Instruction) {
        match *i {
            Instruction::Assign(reg, ref val) |
            Instruction::CastAssign(reg, ref val) => {
                assert_eq!(self.register_size(reg), self.value_size(val));
            }
            Instruction::BinaryOp(dest, BinaryOp::BitOp(_, size), ref a, ref b) |
            Instruction::BinaryOp(dest, BinaryOp::IntOp(_, _, size), ref a, ref b) => {
                assert_eq!(self.register_size(dest), in_bytes(size));
                assert_eq!(self.value_size(a), in_bytes(size));
                assert_eq!(self.value_size(b), in_bytes(size));
            }
            Instruction::BinaryOp(dest, BinaryOp::Eq, ref a, ref b) |
            Instruction::BinaryOp(dest, BinaryOp::Neq, ref a, ref b) => {
                assert_eq!(self.register_size(dest), 1);
                assert_eq!(self.value_size(a), self.value_size(b));
            }
            Instruction::Call(dest, ref sym, ref params) => {
                let callee = &self.functions[sym];
                let out_size = callee.output_layout.unwrap().size;
                assert_eq!(self.register_size(dest), out_size);
                assert_eq!(params.len(), callee.parameters.len());
                for (val, &reg) in params.iter().zip(callee.parameters.iter()) {
                    let reg_size = callee.registers[&reg].size;
                    assert_eq!(self.value_size(val), reg_size);
                }
            }
            Instruction::CallProc(ref sym, ref params) => {
                let callee = &self.functions[sym];
                assert!(callee.output_layout.is_none());
                assert_eq!(params.len(), callee.parameters.len());
                for (val, &reg) in params.iter().zip(callee.parameters.iter()) {
                    let reg_size = callee.registers[&reg].size;
                    assert_eq!(self.value_size(val), reg_size);
                }
            }
            Instruction::CallVirt(_, ref address, _) |
            Instruction::CallProcVirt(ref address, _) => {
                assert_eq!(self.value_size(address), ::ir::POINTER_SIZE);
            }
            Instruction::DerefLoad(_, ref val, _) => {
                assert_eq!(self.value_size(val), ::ir::POINTER_SIZE);
            }
            Instruction::DerefStore(ref address, _, ref value) => {
                assert_eq!(self.value_size(address), ::ir::POINTER_SIZE);
                assert!(self.value_size(value) > 0);
            }
            Instruction::Drop(reg) => {
                assert!(self.function.registers.contains_key(&reg));
            }
            Instruction::Load(dest, reg, offset) => {
                let dest_size = self.register_size(dest);
                let reg_size = self.register_size(reg);
                assert!(dest_size + offset <= reg_size);
            }
            Instruction::Store(reg, offset, ref value) => {
                let reg_size = self.register_size(reg);
                let val_size = self.value_size(value);
                assert!(reg_size >= offset + val_size);
            }
            Instruction::TakeAddress(dest, reg, offset) => {
                assert_eq!(self.register_size(dest), ::ir::POINTER_SIZE);
                let reg_size = self.register_size(reg);
                assert!(offset < reg_size);
            }
            Instruction::UnaryOp(dest, UnaryOp::Negate(_, size), ref value) => {
                assert_eq!(self.register_size(dest), in_bytes(size));
                assert_eq!(self.value_size(value), in_bytes(size));
            }
        }
    }

    fn register_size(&self, reg: Reg) -> u32 {
        self.function.registers[&reg].size
    }

    fn value_size(&self, value: &Value) -> u32 {
        match *value {
            Value::Bytes(_) => ::ir::POINTER_SIZE,
            Value::Int(_, size) => in_bytes(size),
            Value::Reg(reg) => self.register_size(reg),
            Value::Symbol(_) => ::ir::FUNCTION_SIZE,
        }
    }
}

fn in_bytes(size: Size) -> u32 {
    match size {
        Size::Bit8 => 1,
        Size::Bit16 => 2,
        Size::Bit32 => 4,
    }
}

pub fn validate_ir(program: &Program) {
    for f in program.functions.values() {
        let ctx = Context::new(program, f);
        ctx.validate();
    }
}
<commit_msg>fix ir comparision validation<commit_after>use std::collections::HashMap;
use ir::{BinaryOp, Block, BlockEnd, Function, Instruction, IntOp, Program, Reg, Size, Symbol,
         UnaryOp, Value};

struct Context<'a> {
    functions: &'a HashMap<Symbol, Function>,
    function: &'a Function,
}

impl<'a> Context<'a> {
    fn new(program: &'a Program, function: &'a Function) -> Self {
        Context {
            functions: &program.functions,
            function,
        }
    }

    fn validate(&self) {
        if let Some(layout) = self.function.output_layout {
            assert!(layout.size > 0);
        }
        for &layout in self.function.registers.values() {
            assert!(layout.size > 0);
        }
        for &reg in &self.function.parameters {
            assert!(self.function.registers.contains_key(&reg));
        }
        if let Some(block) = self.function.start_block {
            assert!(self.function.blocks.contains_key(&block));
        }
        for block in self.function.blocks.values() {
            self.validate_block(block);
        }
    }

    fn validate_block(&self, block: &Block) {
        for op in &block.ops {
            self.validate_instruction(op);
        }
        match block.end {
            BlockEnd::Branch(ref val, a, b) => {
                assert_eq!(self.value_size(val), 1);
                assert!(self.function.blocks.contains_key(&a));
                assert!(self.function.blocks.contains_key(&b));
            }
            BlockEnd::Jump(block) => {
                assert!(self.function.blocks.contains_key(&block));
            }
            BlockEnd::Return(ref val) => {
                let return_size = self.function.output_layout.unwrap().size;
                assert_eq!(self.value_size(val), return_size);
            }
            BlockEnd::ReturnProc => {
                assert!(self.function.output_layout.is_none());
            }
        }
    }

    fn validate_instruction(&self, i: &Instruction) {
        match *i {
            Instruction::Assign(reg, ref val) |
            Instruction::CastAssign(reg, ref val) => {
                assert_eq!(self.register_size(reg), self.value_size(val));
            }
            Instruction::BinaryOp(dest, BinaryOp::IntOp(IntOp::Greater, _, size), ref a, ref b) |
            Instruction::BinaryOp(dest, BinaryOp::IntOp(IntOp::GreaterEq, _, size), ref a, ref b) |
            Instruction::BinaryOp(dest, BinaryOp::IntOp(IntOp::Less, _, size), ref a, ref b) |
            Instruction::BinaryOp(dest, BinaryOp::IntOp(IntOp::LessEq, _, size), ref a, ref b) => {
                assert_eq!(self.register_size(dest), 1);
                assert_eq!(self.value_size(a), in_bytes(size));
                assert_eq!(self.value_size(b), in_bytes(size));
            }
            Instruction::BinaryOp(dest, BinaryOp::BitOp(_, size), ref a, ref b) |
            Instruction::BinaryOp(dest, BinaryOp::IntOp(_, _, size), ref a, ref b) => {
                assert_eq!(self.register_size(dest), in_bytes(size));
                assert_eq!(self.value_size(a), in_bytes(size));
                assert_eq!(self.value_size(b), in_bytes(size));
            }
            Instruction::BinaryOp(dest, BinaryOp::Eq, ref a, ref b) |
            Instruction::BinaryOp(dest, BinaryOp::Neq, ref a, ref b) => {
                assert_eq!(self.register_size(dest), 1);
                assert_eq!(self.value_size(a), self.value_size(b));
            }
            Instruction::Call(dest, ref sym, ref params) => {
                let callee = &self.functions[sym];
                let out_size = callee.output_layout.unwrap().size;
                assert_eq!(self.register_size(dest), out_size);
                assert_eq!(params.len(), callee.parameters.len());
                for (val, &reg) in params.iter().zip(callee.parameters.iter()) {
                    let reg_size = callee.registers[&reg].size;
                    assert_eq!(self.value_size(val), reg_size);
                }
            }
            Instruction::CallProc(ref sym, ref params) => {
                let callee = &self.functions[sym];
                assert!(callee.output_layout.is_none());
                assert_eq!(params.len(), callee.parameters.len());
                for (val, &reg) in params.iter().zip(callee.parameters.iter()) {
                    let reg_size = callee.registers[&reg].size;
                    assert_eq!(self.value_size(val), reg_size);
                }
            }
            Instruction::CallVirt(_, ref address, _) |
            Instruction::CallProcVirt(ref address, _) => {
                assert_eq!(self.value_size(address), ::ir::POINTER_SIZE);
            }
            Instruction::DerefLoad(_, ref val, _) => {
                assert_eq!(self.value_size(val), ::ir::POINTER_SIZE);
            }
            Instruction::DerefStore(ref address, _, ref value) => {
                assert_eq!(self.value_size(address), ::ir::POINTER_SIZE);
                assert!(self.value_size(value) > 0);
            }
            Instruction::Drop(reg) => {
                assert!(self.function.registers.contains_key(&reg));
            }
            Instruction::Load(dest, reg, offset) => {
                let dest_size = self.register_size(dest);
                let reg_size = self.register_size(reg);
                assert!(dest_size + offset <= reg_size);
            }
            Instruction::Store(reg, offset, ref value) => {
                let reg_size = self.register_size(reg);
                let val_size = self.value_size(value);
                assert!(reg_size >= offset + val_size);
            }
            Instruction::TakeAddress(dest, reg, offset) => {
                assert_eq!(self.register_size(dest), ::ir::POINTER_SIZE);
                let reg_size = self.register_size(reg);
                assert!(offset < reg_size);
            }
            Instruction::UnaryOp(dest, UnaryOp::Negate(_, size), ref value) => {
                assert_eq!(self.register_size(dest), in_bytes(size));
                assert_eq!(self.value_size(value), in_bytes(size));
            }
        }
    }

    fn register_size(&self, reg: Reg) -> u32 {
        self.function.registers[&reg].size
    }

    fn value_size(&self, value: &Value) -> u32 {
        match *value {
            Value::Bytes(_) => ::ir::POINTER_SIZE,
            Value::Int(_, size) => in_bytes(size),
            Value::Reg(reg) => self.register_size(reg),
            Value::Symbol(_) => ::ir::FUNCTION_SIZE,
        }
    }
}

fn in_bytes(size: Size) -> u32 {
    match size {
        Size::Bit8 => 1,
        Size::Bit16 => 2,
        Size::Bit32 => 4,
    }
}

pub fn validate_ir(program: &Program) {
    for f in program.functions.values() {
        let ctx = Context::new(program, f);
        ctx.validate();
    }
}
<|endoftext|>


<commit_before>// Copyright 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.

use prelude::v1::*;
use io::prelude::*;

use any::Any;
use cell::RefCell;
use rt::{backtrace, unwind};
use sys::stdio::Stderr;
use sys_common::thread_info;

thread_local! {
    pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = {
        RefCell::new(None)
    }
}

pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
    let msg = match obj.downcast_ref::<&'static str>() {
        Some(s) => *s,
        None => match obj.downcast_ref::<String>() {
            Some(s) => &s[..],
            None => "Box<Any>",
        }
    };
    let mut err = match Stderr::new() {
        Ok(err) => err,
        _ => return,
    };
    let thread = thread_info::current_thread();
    let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
    let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
    match prev {
        Some(mut stderr) => {
            // FIXME: what to do when the thread printing panics?
            let _ = writeln!(stderr,
                             "thread '{}' panicked at '{}', {}:{}\n",
                             name, msg, file, line);
            if backtrace::log_enabled() {
                let _ = backtrace::write(&mut *stderr);
            }
            let mut s = Some(stderr);
            LOCAL_STDERR.with(|slot| {
                *slot.borrow_mut() = s.take();
            });
        }
        None => {
            let _ = writeln!(&mut err, "thread '{}' panicked at '{}', {}:{}",
                             name, msg, file, line);
            if backtrace::log_enabled() {
                let _ = backtrace::write(&mut err);
            }
        }
    }

    // If this is a double panic, make sure that we printed a backtrace
    // for this panic.
    if unwind::panicking() && !backtrace::log_enabled() {
        let _ = backtrace::write(&mut err);
    }
}
<commit_msg>Auto merge of #26463 - sfackler:stdout-panic-fix, r=alexcrichton<commit_after>// Copyright 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.

use prelude::v1::*;
use io::prelude::*;

use any::Any;
use cell::RefCell;
use rt::{backtrace, unwind};
use sys::stdio::Stderr;
use sys_common::thread_info;

thread_local! {
    pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = {
        RefCell::new(None)
    }
}

pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
    let msg = match obj.downcast_ref::<&'static str>() {
        Some(s) => *s,
        None => match obj.downcast_ref::<String>() {
            Some(s) => &s[..],
            None => "Box<Any>",
        }
    };
    let mut err = Stderr::new().ok();
    let thread = thread_info::current_thread();
    let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
    let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
    match (prev, err.as_mut()) {
        (Some(mut stderr), _) => {
            // FIXME: what to do when the thread printing panics?
            let _ = writeln!(stderr,
                             "thread '{}' panicked at '{}', {}:{}\n",
                             name, msg, file, line);
            if backtrace::log_enabled() {
                let _ = backtrace::write(&mut *stderr);
            }
            let mut s = Some(stderr);
            LOCAL_STDERR.with(|slot| {
                *slot.borrow_mut() = s.take();
            });
        }
        (None, Some(ref mut err)) => {
            let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}",
                             name, msg, file, line);
            if backtrace::log_enabled() {
                let _ = backtrace::write(err);
            }
        }
        _ => {}
    }

    // If this is a double panic, make sure that we printed a backtrace
    // for this panic.
    match err {
        Some(ref mut err) if unwind::panicking() && !backtrace::log_enabled() => {
            let _ = backtrace::write(err);
        }
        _ => {}
    }
}
<|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>std: Be sure to call pthread_attr_destroy<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>// Copyright 2013 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.

//! A wrapper around any Reader to treat it as an RNG.

use Rng;

/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
/// It will fail if it there is insufficient data to fulfill a request.
///
/// # Example
///
/// ```rust
/// use rand::{reader, Rng};
/// use std::io::MemReader;
///
/// let mut rng = reader::ReaderRng::new(MemReader::new(~[1,2,3,4,5,6,7,8]));
/// println!("{:x}", rng.gen::<uint>());
/// ```
pub struct ReaderRng<R> {
    priv reader: R
}

impl<R: Reader> ReaderRng<R> {
    /// Create a new `ReaderRng` from a `Reader`.
    pub fn new(r: R) -> ReaderRng<R> {
        ReaderRng {
            reader: r
        }
    }
}

impl<R: Reader> Rng for ReaderRng<R> {
    fn next_u32(&mut self) -> u32 {
        // This is designed for speed: reading a LE integer on a LE
        // platform just involves blitting the bytes into the memory
        // of the u32, similarly for BE on BE; avoiding byteswapping.
        if cfg!(target_endian="little") {
            self.reader.read_le_u32().unwrap()
        } else {
            self.reader.read_be_u32().unwrap()
        }
    }
    fn next_u64(&mut self) -> u64 {
        // see above for explanation.
        if cfg!(target_endian="little") {
            self.reader.read_le_u64().unwrap()
        } else {
            self.reader.read_be_u64().unwrap()
        }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        if v.len() == 0 { return }
        match self.reader.read(v) {
            Ok(n) if n == v.len() => return,
            Ok(n) => fail!("ReaderRng.fill_bytes could not fill buffer: \
                            read {} out of {} bytes.", n, v.len()),
            Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
        }
    }
}

#[cfg(test)]
mod test {
    use super::ReaderRng;
    use std::io::MemReader;
    use std::cast;
    use Rng;

    #[test]
    fn test_reader_rng_u64() {
        // transmute from the target to avoid endianness concerns.
        let v = ~[1u64, 2u64, 3u64];
        let bytes: ~[u8] = unsafe {cast::transmute(v)};
        let mut rng = ReaderRng::new(MemReader::new(bytes));

        assert_eq!(rng.next_u64(), 1);
        assert_eq!(rng.next_u64(), 2);
        assert_eq!(rng.next_u64(), 3);
    }
    #[test]
    fn test_reader_rng_u32() {
        // transmute from the target to avoid endianness concerns.
        let v = ~[1u32, 2u32, 3u32];
        let bytes: ~[u8] = unsafe {cast::transmute(v)};
        let mut rng = ReaderRng::new(MemReader::new(bytes));

        assert_eq!(rng.next_u32(), 1);
        assert_eq!(rng.next_u32(), 2);
        assert_eq!(rng.next_u32(), 3);
    }
    #[test]
    fn test_reader_rng_fill_bytes() {
        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
        let mut w = [0u8, .. 8];

        let mut rng = ReaderRng::new(MemReader::new(v.to_owned()));
        rng.fill_bytes(w);

        assert!(v == w);
    }

    #[test]
    #[should_fail]
    fn test_reader_rng_insufficient_bytes() {
        let mut rng = ReaderRng::new(MemReader::new(~[]));
        let mut v = [0u8, .. 3];
        rng.fill_bytes(v);
    }
}
<commit_msg>rand: Use fill() instead of read()<commit_after>// Copyright 2013 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.

//! A wrapper around any Reader to treat it as an RNG.

use Rng;

/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
/// It will fail if it there is insufficient data to fulfill a request.
///
/// # Example
///
/// ```rust
/// use rand::{reader, Rng};
/// use std::io::MemReader;
///
/// let mut rng = reader::ReaderRng::new(MemReader::new(~[1,2,3,4,5,6,7,8]));
/// println!("{:x}", rng.gen::<uint>());
/// ```
pub struct ReaderRng<R> {
    priv reader: R
}

impl<R: Reader> ReaderRng<R> {
    /// Create a new `ReaderRng` from a `Reader`.
    pub fn new(r: R) -> ReaderRng<R> {
        ReaderRng {
            reader: r
        }
    }
}

impl<R: Reader> Rng for ReaderRng<R> {
    fn next_u32(&mut self) -> u32 {
        // This is designed for speed: reading a LE integer on a LE
        // platform just involves blitting the bytes into the memory
        // of the u32, similarly for BE on BE; avoiding byteswapping.
        if cfg!(target_endian="little") {
            self.reader.read_le_u32().unwrap()
        } else {
            self.reader.read_be_u32().unwrap()
        }
    }
    fn next_u64(&mut self) -> u64 {
        // see above for explanation.
        if cfg!(target_endian="little") {
            self.reader.read_le_u64().unwrap()
        } else {
            self.reader.read_be_u64().unwrap()
        }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        if v.len() == 0 { return }
        match self.reader.fill(v) {
            Ok(()) => {}
            Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
        }
    }
}

#[cfg(test)]
mod test {
    use super::ReaderRng;
    use std::io::MemReader;
    use std::cast;
    use Rng;

    #[test]
    fn test_reader_rng_u64() {
        // transmute from the target to avoid endianness concerns.
        let v = ~[1u64, 2u64, 3u64];
        let bytes: ~[u8] = unsafe {cast::transmute(v)};
        let mut rng = ReaderRng::new(MemReader::new(bytes));

        assert_eq!(rng.next_u64(), 1);
        assert_eq!(rng.next_u64(), 2);
        assert_eq!(rng.next_u64(), 3);
    }
    #[test]
    fn test_reader_rng_u32() {
        // transmute from the target to avoid endianness concerns.
        let v = ~[1u32, 2u32, 3u32];
        let bytes: ~[u8] = unsafe {cast::transmute(v)};
        let mut rng = ReaderRng::new(MemReader::new(bytes));

        assert_eq!(rng.next_u32(), 1);
        assert_eq!(rng.next_u32(), 2);
        assert_eq!(rng.next_u32(), 3);
    }
    #[test]
    fn test_reader_rng_fill_bytes() {
        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
        let mut w = [0u8, .. 8];

        let mut rng = ReaderRng::new(MemReader::new(v.to_owned()));
        rng.fill_bytes(w);

        assert!(v == w);
    }

    #[test]
    #[should_fail]
    fn test_reader_rng_insufficient_bytes() {
        let mut rng = ReaderRng::new(MemReader::new(~[]));
        let mut v = [0u8, .. 3];
        rng.fill_bytes(v);
    }
}
<|endoftext|>


<commit_before>
use geometry::Point;
use core::rand::RngUtil;
use core::float::pow;
mod geometry;

//
// Cellule
//

struct Cell {
    center: Point,
    id: uint,
    radius: f64,
    velocity: Point,
    acc: Point,
    generation: int,
    age: int
}

pub impl Cell {
    fn new(ident: uint) -> Cell {
        let radius = 1.0;
        //let r=rand::random::<float>();
        //io::println(fmt!("%f\n", r));
        let center : Point =rand::random();

        Cell{ center: center, id: ident, radius: radius, velocity: Point::new(), acc: Point::new(), generation: 0, age:0}
    }

    fn move(&mut self, tumeur: &Crowd, dt: f64) {
        let old_acc = copy self.acc;

        // Nouvelle position
        self.center+=self.velocity+self.acc*(0.5*float::pow(dt,2.0) as f64);

        // Force aléatoire
        let F_alea: Point=rand::random();
        self.acc=self.calc_rep_force(tumeur)+F_alea*(0.0005 as f64);

        // Nouvelle vitesse
        let lambda : f64=5.0;
        let denom : f64 = 1.0/(1.0+lambda*dt/2.0);
        self.velocity=(self.velocity*(1.0-lambda*dt/2.0)+(self.acc+old_acc)*dt/(2.0 as f64))*denom;

    }

    fn replicate(&mut self, tumeur: &Crowd, dt: f64) {
        io::println(fmt!("%d @ %f\n",tumeur.size() as int, dt as float));

        self.age+=1;
    }

    fn calc_rep_force(&self, tumeur: &Crowd) -> Point {
        let seuil=3.0*self.radius;
        let mut force = Point::new();
        for tumeur.cells.each |&cell| {
            if(cell.id != self.id) {
                let dist_cells=(self.dist(cell)+2.0*self.radius)/seuil;
                let factor = 1.0/pow(dist_cells,3.0)*1e-7 as f64;
                force += (self.center-cell.center)*factor;
            }
        }
        force
    }

    fn dist(&self, other: &Cell) -> f64 {
        self.center.dist(&other.center)
    }

}

impl ToStr for Cell {
    fn to_str(&self) -> ~str {
        fmt!("%d @ (%f, %f)", self.id as int, self.center.x as float, self.center.y as float)
    }
}

#[test]
fn test_new() {
    let cell1=Cell::new(0);
    let cell2=Cell::new(1);
    assert!(cell1.center != cell2.center);
}
//
// Population
//

struct Crowd {
    cells : ~[@mut Cell],
    time : float
}

pub impl Crowd {
    fn new(init_pop : uint) -> Crowd {

        let mut pop : ~[@mut Cell]=~[];
        for uint::range(1,init_pop+1) |num| {
            let lonely_one = @mut Cell::new(num);
            pop.push(copy lonely_one);
        }
        Crowd{ cells : pop, time: 0.0}
    }

    fn size(&self) -> uint {
        self.cells.len()
    }

    fn evolve(&self, dt: f64) {
        for self.cells.each |cell| {
            cell.move(self, dt);
        }
    }
}

impl ToStr for Crowd {
    fn to_str(&self) -> ~str {
        let mut desc =~"";
        for self.cells.each |cell| {
            let mut lcell_desc=~"";
            lcell_desc.push_str(cell.to_str()); lcell_desc.push_str("\n");
             desc.push_str(lcell_desc);
        }
        desc
    }
}

#[test]
fn test_size() {
    let crowd=Crowd::new(13);
    assert!(crowd.size()==13);
}
<commit_msg>Deux méthodes pour avoir directement les coordonnées du centre de la cellule<commit_after>
use geometry::Point;
use core::rand::RngUtil;
use core::float::pow;
mod geometry;

//
// Cellule
//

struct Cell {
    center: Point,
    id: uint,
    radius: f64,
    velocity: Point,
    acc: Point,
    generation: int,
    age: int
}

pub impl Cell {
    fn new(ident: uint) -> Cell {
        let radius = 1.0;
        //let r=rand::random::<float>();
        //io::println(fmt!("%f\n", r));
        let center : Point =rand::random();

        Cell{ center: center, id: ident, radius: radius, velocity: Point::new(), acc: Point::new(), generation: 0, age:0}
    }

    fn move(&mut self, tumeur: &Crowd, dt: f64) {
        let old_acc = copy self.acc;

        // Nouvelle position
        self.center+=self.velocity+self.acc*(0.5*float::pow(dt,2.0) as f64);

        // Force aléatoire
        let F_alea: Point=rand::random();
        self.acc=self.calc_rep_force(tumeur)+F_alea*(0.0005 as f64);

        // Nouvelle vitesse
        let lambda : f64=5.0;
        let denom : f64 = 1.0/(1.0+lambda*dt/2.0);
        self.velocity=(self.velocity*(1.0-lambda*dt/2.0)+(self.acc+old_acc)*dt/(2.0 as f64))*denom;

    }

    fn replicate(&mut self, tumeur: &Crowd, dt: f64) {
        io::println(fmt!("%d @ %f\n",tumeur.size() as int, dt as float));

        self.age+=1;
    }

    fn calc_rep_force(&self, tumeur: &Crowd) -> Point {
        let seuil=3.0*self.radius;
        let mut force = Point::new();
        for tumeur.cells.each |&cell| {
            if(cell.id != self.id) {
                let dist_cells=(self.dist(cell)+2.0*self.radius)/seuil;
                let factor = 1.0/pow(dist_cells,3.0)*1e-7 as f64;
                force += (self.center-cell.center)*factor;
            }
        }
        force
    }

    #[inline(always)]
    fn x(&self) -> f64 {
        self.center.x
    }

    #[inline(always)]
    fn y(&self) -> f64 {
        self.center.y
    }

    fn dist(&self, other: &Cell) -> f64 {
        self.center.dist(&other.center)
    }

}

impl ToStr for Cell {
    fn to_str(&self) -> ~str {
        fmt!("%d @ (%f, %f)", self.id as int, self.center.x as float, self.center.y as float)
    }
}

#[test]
fn test_new() {
    let cell1=Cell::new(0);
    let cell2=Cell::new(1);
    assert!(cell1.center != cell2.center);
}

//
// Population
//

struct Crowd {
    cells : ~[@mut Cell],
    time : float
}

pub impl Crowd {
    fn new(init_pop : uint) -> Crowd {

        let mut pop : ~[@mut Cell]=~[];
        for uint::range(1,init_pop+1) |num| {
            let lonely_one = @mut Cell::new(num);
            pop.push(copy lonely_one);
        }
        Crowd{ cells : pop, time: 0.0}
    }

    fn size(&self) -> uint {
        self.cells.len()
    }

    fn evolve(&self, dt: f64) {
        for self.cells.each |cell| {
            cell.move(self, dt);
        }
    }
}

impl ToStr for Crowd {
    fn to_str(&self) -> ~str {
        let mut desc =~"";
        for self.cells.each |cell| {
            let mut lcell_desc=~"";
            lcell_desc.push_str(cell.to_str()); lcell_desc.push_str("\n");
             desc.push_str(lcell_desc);
        }
        desc
    }
}

#[test]
fn test_size() {
    let crowd=Crowd::new(13);
    assert!(crowd.size()==13);
}
<|endoftext|>