<commit_before>// Lumol, an extensible molecular simulation engine
// Copyright (C) Lumol's contributors — BSD license

//! [Chemfiles][Chemfiles] conversion for Lumol.
//!
//! [Chemfiles]: https://Chemfiles.github.io/
use sys::{System, Particle, Molecule, UnitCell, CellShape};
use types::Vector3D;
use chemfiles;

use std::fmt;
use std::error;
use std::path::Path;

/// Possible error when reading and writing to trajectories
#[derive(Debug)]
pub struct TrajectoryError(chemfiles::Error);

impl From<chemfiles::Error> for TrajectoryError {
    fn from(err: chemfiles::Error) -> TrajectoryError {
        TrajectoryError(err)
    }
}

impl fmt::Display for TrajectoryError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(fmt)
    }
}

impl error::Error for TrajectoryError {
    fn description(&self) -> &str {
        self.0.description()
    }
}

/// Convert Chemfiles types to Lumol types
pub trait ToLumol {
    /// Output type
    type Output;
    /// Conversion function
    fn to_lumol(self) -> TrajectoryResult<Self::Output>;
}

impl ToLumol for chemfiles::Atom {
    type Output = Particle;
    fn to_lumol(self) -> TrajectoryResult<Particle> {
        let name = try!(self.name());
        let mut part = Particle::new(name);
        let mass = try!(self.mass());
        part.mass = mass as f64;
        Ok(part)
    }
}

impl ToLumol for chemfiles::UnitCell {
    type Output = UnitCell;
    fn to_lumol(self) -> TrajectoryResult<UnitCell> {
        let cell_type = try!(self.shape());
        let cell = match cell_type {
            chemfiles::CellShape::Infinite => UnitCell::new(),
            chemfiles::CellShape::Orthorhombic => {
                let (a, b, c) = try!(self.lengths());
                UnitCell::ortho(a, b, c)
            },
            chemfiles::CellShape::Triclinic => {
                let (a, b, c) = try!(self.lengths());
                let (alpha, beta, gamma) = try!(self.angles());
                UnitCell::triclinic(a, b, c, alpha, beta, gamma)
            }
        };
        Ok(cell)
    }
}

impl ToLumol for chemfiles::Frame {
    type Output = System;
    fn to_lumol(self) -> TrajectoryResult<System> {
        let cell = try!(self.cell());
        let cell = try!(cell.to_lumol());
        let mut system = System::with_cell(cell);
        let topology = try!(self.topology());
        let natoms = try!(self.natoms()) as usize;

        let positions = try!(self.positions());
        for i in 0..natoms {
            let atom = try!(topology.atom(i as u64));
            let particle = try!(atom.to_lumol());

            system.add_particle(particle);
            let position = Vector3D::new(
                positions[i][0],
                positions[i][1],
                positions[i][2]
            );
            system[i].position = position;
        }

        let mut bonds = try!(topology.bonds());
        while let Some(bond) = bonds.pop() {
            let permutations = system.add_bond(bond[0] as usize, bond[1] as usize);
            apply_particle_permutation(&mut bonds, &permutations);
        }
        Ok(system)
    }
}

fn apply_particle_permutation(bonds: &mut Vec<[u64; 2]>, permutations: &[(usize, usize)]) {
    for bond in bonds {
        // Search for a permutation applying to the first atom of the bond. We
        // need to stop just after the first permutations is found, because we
        // can have a permutation looking like this: [1 -> 2, 2 -> 3, 3 -> 4].
        // If we do not stop after the first match, then all indexes in 1-3
        // range will become 4.
        for permutation in permutations {
            if bond[0] == permutation.0 as u64 {
                bond[0] = permutation.1 as u64;
                break;
            }
        }

        // Now we look for permutations applying to the second atom of the bond
        for permutation in permutations {
            if bond[1] == permutation.0 as u64 {
                bond[1] = permutation.1 as u64;
                break;
            }
        }
    }
}

/******************************************************************************/

/// Convert Lumol types to Chemfiles types
pub trait ToChemfiles {
    /// Output type
    type Output;
    /// Conversion function
    fn to_chemfiles(&self) -> TrajectoryResult<Self::Output>;
}

impl ToChemfiles for Particle {
    type Output = chemfiles::Atom;
    fn to_chemfiles(&self) -> TrajectoryResult<chemfiles::Atom> {
        let mut atom = try!(chemfiles::Atom::new(self.name()));
        try!(atom.set_mass(self.mass));
        return Ok(atom);
    }
}

impl ToChemfiles for UnitCell {
    type Output = chemfiles::UnitCell;
    fn to_chemfiles(&self) -> TrajectoryResult<chemfiles::UnitCell> {
        let res = match self.shape() {
            CellShape::Infinite => {
                try!(chemfiles::UnitCell::infinite())
            }
            CellShape::Orthorhombic => {
                let (a, b, c) = (self.a(), self.b(), self.c());
                try!(chemfiles::UnitCell::new(a, b, c))
            },
            CellShape::Triclinic => {
                let (a, b, c) = (self.a(), self.b(), self.c());
                let (alpha, beta, gamma) = (self.alpha(), self.beta(), self.gamma());
                try!(chemfiles::UnitCell::triclinic(a, b, c, alpha, beta, gamma))
            },
        };
        return Ok(res);
    }
}

impl ToChemfiles for System {
    type Output = chemfiles::Frame;
    fn to_chemfiles(&self) -> TrajectoryResult<chemfiles::Frame> {
        let mut frame = try!(chemfiles::Frame::new());
        try!(frame.resize(self.size() as u64));
        try!(frame.set_step(self.step() as u64));

        {
            let positions = try!(frame.positions_mut());
            for (i, particle) in self.iter().enumerate() {
                positions[i][0] = particle.position[0];
                positions[i][1] = particle.position[1];
                positions[i][2] = particle.position[2];
            }
        }

        {
            try!(frame.add_velocities());
            let velocities = try!(frame.velocities_mut());
            for (i, particle) in self.iter().enumerate() {
                velocities[i][0] = particle.velocity[0];
                velocities[i][1] = particle.velocity[1];
                velocities[i][2] = particle.velocity[2];
            }
        }

        let mut topology = try!(chemfiles::Topology::new());
        for particle in self {
            let atom = try!(particle.to_chemfiles());
            try!(topology.add_atom(&atom));
        }

        for molecule in self.molecules() {
            for bond in molecule.bonds() {
                try!(topology.add_bond(bond.i() as u64, bond.j() as u64));
            }
        }

        try!(frame.set_topology(&topology));
        let cell = try!(self.cell.to_chemfiles());
        try!(frame.set_cell(&cell));
        Ok(frame)
    }
}

/******************************************************************************/

/// A Trajectory is a file containing one or more successive simulation steps
pub struct Trajectory(chemfiles::Trajectory);

/// Result type for all Trajectory operations
pub type TrajectoryResult<T> = Result<T, TrajectoryError>;

impl Trajectory {
    /// Open an existing file at `path` for reading.
    pub fn open<P: AsRef<Path>>(path: P) -> TrajectoryResult<Trajectory> {
        let trajectory = try!(chemfiles::Trajectory::open(path, 'r'));
        return Ok(Trajectory(trajectory));
    }

    /// Create a new file at `path` for writing, overwrite any existing file.
    pub fn create<P: AsRef<Path>>(path: P) -> TrajectoryResult<Trajectory> {
        let trajectory = try!(chemfiles::Trajectory::open(path, 'w'));
        return Ok(Trajectory(trajectory));
    }

    /// Read the next step of the trajectory
    pub fn read(&mut self) -> TrajectoryResult<System> {
        let mut frame = try!(chemfiles::Frame::new());
        try!(self.0.read(&mut frame));
        return frame.to_lumol();
    }

    /// Read the next step of the trajectory, and guess the bonds of the
    /// resulting System.
    pub fn read_guess_bonds(&mut self) -> TrajectoryResult<System> {
        let mut frame = try!(chemfiles::Frame::new());
        try!(self.0.read(&mut frame));
        try!(frame.guess_topology());
        return frame.to_lumol();
    }

    /// Write the system to the trajectory.
    pub fn write(&mut self, system: &System) -> TrajectoryResult<()> {
        let frame = try!(system.to_chemfiles());
        try!(self.0.write(&frame));
        Ok(())
    }

    /// Get access to the Chemfiles trajectory, and the associated features
    // TODO: use partial privacy for this function
    pub fn as_chemfiles(&mut self) -> &mut chemfiles::Trajectory {
        &mut self.0
    }
}

/// Read a the first molecule from the file at `path`. If no bond information
/// exists in the file, bonds are guessed.
pub fn read_molecule<P: AsRef<Path>>(path: P) -> TrajectoryResult<(Molecule, Vec<Particle>)> {
    let mut trajectory = try!(chemfiles::Trajectory::open(&path, 'r'));
    let mut frame = try!(chemfiles::Frame::new());
    try!(trajectory.read(&mut frame));

    // Only guess the topology when we have no bond information
    let topology = try!(frame.topology());
    if try!(topology.bonds_count()) == 0 {
        try!(frame.guess_topology());
    }
    let system = try!(frame.to_lumol());

    assert!(
        !system.is_empty(),
        "No molecule in the file at {}", path.as_ref().display()
    );
    let molecule = system.molecule(0).clone();
    let mut particles = Vec::new();
    for i in &molecule {
        particles.push(system[i].clone());
    }
    return Ok((molecule, particles));
}

/// Guess the bonds in a system using Chemfiles algorithm
pub fn guess_bonds(system: &System) -> TrajectoryResult<System> {
    let mut frame = try!(system.to_chemfiles());
    try!(frame.guess_topology());
    return frame.to_lumol();
}

#[cfg(test)]
mod tests {
    extern crate tempfile;
    use self::tempfile::NamedTempFileOptions;

    use super::*;
    use std::io::prelude::*;
    use sys::molecule_type;
    use sys::{Bond, Angle};

    static WATER: &'static str = "3

O 0.0 0.0 0.0
H 1.0 0.0 0.0
H 0.0 1.0 0.0
";

    static PROPANE: &'static str = "11

H     -1.306761     0.917434     0.885782
C     -1.277333     0.278101     0.000000
H     -2.172669    -0.348524    -0.000126
H     -1.306638     0.917616    -0.885655
C      0.000000    -0.596258     0.000000
H      0.000000    -1.247870    -0.879715
H      0.000000    -1.247870     0.879715
C      1.277333     0.278101     0.000000
H      1.306675     0.917562     0.885693
H      1.306724     0.917489    -0.885744
H      2.172669     -0.348524    0.000051
";

    #[test]
    fn read_water() {
        let mut file = NamedTempFileOptions::new().suffix(".xyz").create().unwrap();
        write!(file, "{}", WATER).unwrap();

        let (molecule, atoms) = read_molecule(file.path()).unwrap();

        assert_eq!(molecule.size(), 3);
        assert_eq!(molecule.size(), atoms.len());

        assert_eq!(molecule.bonds().len(), 2);
        assert!(molecule.bonds().contains(&Bond::new(0, 1)));
        assert!(molecule.bonds().contains(&Bond::new(0, 2)));

        assert_eq!(molecule.angles().len(), 1);
        assert!(molecule.angles().contains(&Angle::new(1, 0, 2)));

        assert!(molecule.dihedrals().is_empty());

        assert_eq!(atoms[0].name(), "O");
        assert_eq!(atoms[1].name(), "H");
        assert_eq!(atoms[2].name(), "H");

        // This is only a simple regression test on the moltype function. Feel
        // free to change the value if the molecule type algorithm change.
        assert_eq!(molecule_type(&molecule, &atoms), 2727145596042757306);
    }

    #[test]
    fn read_propane() {
        let mut file = NamedTempFileOptions::new().suffix(".xyz").create().unwrap();
        write!(file, "{}", PROPANE).unwrap();

        let (molecule, atoms) = read_molecule(file.path()).unwrap();

        assert_eq!(molecule.size(), 11);
        assert_eq!(molecule.size(), atoms.len());

        assert_eq!(molecule.bonds().len(), 10);
        assert_eq!(molecule.angles().len(), 18);
        assert_eq!(molecule.dihedrals().len(), 18);

        // This is only a simple regression test on the moltype function. Feel
        // free to change the value if the molecule type algorithm change.
        assert_eq!(molecule_type(&molecule, &atoms), 2028056351119909064);
    }
}
<commit_msg>Fix link to chemfiles<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) Lumol's contributors — BSD license

//! [Chemfiles][Chemfiles] conversion for Lumol.
//!
//! [Chemfiles]: https://chemfiles.org/
use sys::{System, Particle, Molecule, UnitCell, CellShape};
use types::Vector3D;
use chemfiles;

use std::fmt;
use std::error;
use std::path::Path;

/// Possible error when reading and writing to trajectories
#[derive(Debug)]
pub struct TrajectoryError(chemfiles::Error);

impl From<chemfiles::Error> for TrajectoryError {
    fn from(err: chemfiles::Error) -> TrajectoryError {
        TrajectoryError(err)
    }
}

impl fmt::Display for TrajectoryError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(fmt)
    }
}

impl error::Error for TrajectoryError {
    fn description(&self) -> &str {
        self.0.description()
    }
}

/// Convert Chemfiles types to Lumol types
pub trait ToLumol {
    /// Output type
    type Output;
    /// Conversion function
    fn to_lumol(self) -> TrajectoryResult<Self::Output>;
}

impl ToLumol for chemfiles::Atom {
    type Output = Particle;
    fn to_lumol(self) -> TrajectoryResult<Particle> {
        let name = try!(self.name());
        let mut part = Particle::new(name);
        let mass = try!(self.mass());
        part.mass = mass as f64;
        Ok(part)
    }
}

impl ToLumol for chemfiles::UnitCell {
    type Output = UnitCell;
    fn to_lumol(self) -> TrajectoryResult<UnitCell> {
        let cell_type = try!(self.shape());
        let cell = match cell_type {
            chemfiles::CellShape::Infinite => UnitCell::new(),
            chemfiles::CellShape::Orthorhombic => {
                let (a, b, c) = try!(self.lengths());
                UnitCell::ortho(a, b, c)
            },
            chemfiles::CellShape::Triclinic => {
                let (a, b, c) = try!(self.lengths());
                let (alpha, beta, gamma) = try!(self.angles());
                UnitCell::triclinic(a, b, c, alpha, beta, gamma)
            }
        };
        Ok(cell)
    }
}

impl ToLumol for chemfiles::Frame {
    type Output = System;
    fn to_lumol(self) -> TrajectoryResult<System> {
        let cell = try!(self.cell());
        let cell = try!(cell.to_lumol());
        let mut system = System::with_cell(cell);
        let topology = try!(self.topology());
        let natoms = try!(self.natoms()) as usize;

        let positions = try!(self.positions());
        for i in 0..natoms {
            let atom = try!(topology.atom(i as u64));
            let particle = try!(atom.to_lumol());

            system.add_particle(particle);
            let position = Vector3D::new(
                positions[i][0],
                positions[i][1],
                positions[i][2]
            );
            system[i].position = position;
        }

        let mut bonds = try!(topology.bonds());
        while let Some(bond) = bonds.pop() {
            let permutations = system.add_bond(bond[0] as usize, bond[1] as usize);
            apply_particle_permutation(&mut bonds, &permutations);
        }
        Ok(system)
    }
}

fn apply_particle_permutation(bonds: &mut Vec<[u64; 2]>, permutations: &[(usize, usize)]) {
    for bond in bonds {
        // Search for a permutation applying to the first atom of the bond. We
        // need to stop just after the first permutations is found, because we
        // can have a permutation looking like this: [1 -> 2, 2 -> 3, 3 -> 4].
        // If we do not stop after the first match, then all indexes in 1-3
        // range will become 4.
        for permutation in permutations {
            if bond[0] == permutation.0 as u64 {
                bond[0] = permutation.1 as u64;
                break;
            }
        }

        // Now we look for permutations applying to the second atom of the bond
        for permutation in permutations {
            if bond[1] == permutation.0 as u64 {
                bond[1] = permutation.1 as u64;
                break;
            }
        }
    }
}

/******************************************************************************/

/// Convert Lumol types to Chemfiles types
pub trait ToChemfiles {
    /// Output type
    type Output;
    /// Conversion function
    fn to_chemfiles(&self) -> TrajectoryResult<Self::Output>;
}

impl ToChemfiles for Particle {
    type Output = chemfiles::Atom;
    fn to_chemfiles(&self) -> TrajectoryResult<chemfiles::Atom> {
        let mut atom = try!(chemfiles::Atom::new(self.name()));
        try!(atom.set_mass(self.mass));
        return Ok(atom);
    }
}

impl ToChemfiles for UnitCell {
    type Output = chemfiles::UnitCell;
    fn to_chemfiles(&self) -> TrajectoryResult<chemfiles::UnitCell> {
        let res = match self.shape() {
            CellShape::Infinite => {
                try!(chemfiles::UnitCell::infinite())
            }
            CellShape::Orthorhombic => {
                let (a, b, c) = (self.a(), self.b(), self.c());
                try!(chemfiles::UnitCell::new(a, b, c))
            },
            CellShape::Triclinic => {
                let (a, b, c) = (self.a(), self.b(), self.c());
                let (alpha, beta, gamma) = (self.alpha(), self.beta(), self.gamma());
                try!(chemfiles::UnitCell::triclinic(a, b, c, alpha, beta, gamma))
            },
        };
        return Ok(res);
    }
}

impl ToChemfiles for System {
    type Output = chemfiles::Frame;
    fn to_chemfiles(&self) -> TrajectoryResult<chemfiles::Frame> {
        let mut frame = try!(chemfiles::Frame::new());
        try!(frame.resize(self.size() as u64));
        try!(frame.set_step(self.step() as u64));

        {
            let positions = try!(frame.positions_mut());
            for (i, particle) in self.iter().enumerate() {
                positions[i][0] = particle.position[0];
                positions[i][1] = particle.position[1];
                positions[i][2] = particle.position[2];
            }
        }

        {
            try!(frame.add_velocities());
            let velocities = try!(frame.velocities_mut());
            for (i, particle) in self.iter().enumerate() {
                velocities[i][0] = particle.velocity[0];
                velocities[i][1] = particle.velocity[1];
                velocities[i][2] = particle.velocity[2];
            }
        }

        let mut topology = try!(chemfiles::Topology::new());
        for particle in self {
            let atom = try!(particle.to_chemfiles());
            try!(topology.add_atom(&atom));
        }

        for molecule in self.molecules() {
            for bond in molecule.bonds() {
                try!(topology.add_bond(bond.i() as u64, bond.j() as u64));
            }
        }

        try!(frame.set_topology(&topology));
        let cell = try!(self.cell.to_chemfiles());
        try!(frame.set_cell(&cell));
        Ok(frame)
    }
}

/******************************************************************************/

/// A Trajectory is a file containing one or more successive simulation steps
pub struct Trajectory(chemfiles::Trajectory);

/// Result type for all Trajectory operations
pub type TrajectoryResult<T> = Result<T, TrajectoryError>;

impl Trajectory {
    /// Open an existing file at `path` for reading.
    pub fn open<P: AsRef<Path>>(path: P) -> TrajectoryResult<Trajectory> {
        let trajectory = try!(chemfiles::Trajectory::open(path, 'r'));
        return Ok(Trajectory(trajectory));
    }

    /// Create a new file at `path` for writing, overwrite any existing file.
    pub fn create<P: AsRef<Path>>(path: P) -> TrajectoryResult<Trajectory> {
        let trajectory = try!(chemfiles::Trajectory::open(path, 'w'));
        return Ok(Trajectory(trajectory));
    }

    /// Read the next step of the trajectory
    pub fn read(&mut self) -> TrajectoryResult<System> {
        let mut frame = try!(chemfiles::Frame::new());
        try!(self.0.read(&mut frame));
        return frame.to_lumol();
    }

    /// Read the next step of the trajectory, and guess the bonds of the
    /// resulting System.
    pub fn read_guess_bonds(&mut self) -> TrajectoryResult<System> {
        let mut frame = try!(chemfiles::Frame::new());
        try!(self.0.read(&mut frame));
        try!(frame.guess_topology());
        return frame.to_lumol();
    }

    /// Write the system to the trajectory.
    pub fn write(&mut self, system: &System) -> TrajectoryResult<()> {
        let frame = try!(system.to_chemfiles());
        try!(self.0.write(&frame));
        Ok(())
    }

    /// Get access to the Chemfiles trajectory, and the associated features
    // TODO: use partial privacy for this function
    pub fn as_chemfiles(&mut self) -> &mut chemfiles::Trajectory {
        &mut self.0
    }
}

/// Read a the first molecule from the file at `path`. If no bond information
/// exists in the file, bonds are guessed.
pub fn read_molecule<P: AsRef<Path>>(path: P) -> TrajectoryResult<(Molecule, Vec<Particle>)> {
    let mut trajectory = try!(chemfiles::Trajectory::open(&path, 'r'));
    let mut frame = try!(chemfiles::Frame::new());
    try!(trajectory.read(&mut frame));

    // Only guess the topology when we have no bond information
    let topology = try!(frame.topology());
    if try!(topology.bonds_count()) == 0 {
        try!(frame.guess_topology());
    }
    let system = try!(frame.to_lumol());

    assert!(
        !system.is_empty(),
        "No molecule in the file at {}", path.as_ref().display()
    );
    let molecule = system.molecule(0).clone();
    let mut particles = Vec::new();
    for i in &molecule {
        particles.push(system[i].clone());
    }
    return Ok((molecule, particles));
}

/// Guess the bonds in a system using Chemfiles algorithm
pub fn guess_bonds(system: &System) -> TrajectoryResult<System> {
    let mut frame = try!(system.to_chemfiles());
    try!(frame.guess_topology());
    return frame.to_lumol();
}

#[cfg(test)]
mod tests {
    extern crate tempfile;
    use self::tempfile::NamedTempFileOptions;

    use super::*;
    use std::io::prelude::*;
    use sys::molecule_type;
    use sys::{Bond, Angle};

    static WATER: &'static str = "3

O 0.0 0.0 0.0
H 1.0 0.0 0.0
H 0.0 1.0 0.0
";

    static PROPANE: &'static str = "11

H     -1.306761     0.917434     0.885782
C     -1.277333     0.278101     0.000000
H     -2.172669    -0.348524    -0.000126
H     -1.306638     0.917616    -0.885655
C      0.000000    -0.596258     0.000000
H      0.000000    -1.247870    -0.879715
H      0.000000    -1.247870     0.879715
C      1.277333     0.278101     0.000000
H      1.306675     0.917562     0.885693
H      1.306724     0.917489    -0.885744
H      2.172669     -0.348524    0.000051
";

    #[test]
    fn read_water() {
        let mut file = NamedTempFileOptions::new().suffix(".xyz").create().unwrap();
        write!(file, "{}", WATER).unwrap();

        let (molecule, atoms) = read_molecule(file.path()).unwrap();

        assert_eq!(molecule.size(), 3);
        assert_eq!(molecule.size(), atoms.len());

        assert_eq!(molecule.bonds().len(), 2);
        assert!(molecule.bonds().contains(&Bond::new(0, 1)));
        assert!(molecule.bonds().contains(&Bond::new(0, 2)));

        assert_eq!(molecule.angles().len(), 1);
        assert!(molecule.angles().contains(&Angle::new(1, 0, 2)));

        assert!(molecule.dihedrals().is_empty());

        assert_eq!(atoms[0].name(), "O");
        assert_eq!(atoms[1].name(), "H");
        assert_eq!(atoms[2].name(), "H");

        // This is only a simple regression test on the moltype function. Feel
        // free to change the value if the molecule type algorithm change.
        assert_eq!(molecule_type(&molecule, &atoms), 2727145596042757306);
    }

    #[test]
    fn read_propane() {
        let mut file = NamedTempFileOptions::new().suffix(".xyz").create().unwrap();
        write!(file, "{}", PROPANE).unwrap();

        let (molecule, atoms) = read_molecule(file.path()).unwrap();

        assert_eq!(molecule.size(), 11);
        assert_eq!(molecule.size(), atoms.len());

        assert_eq!(molecule.bonds().len(), 10);
        assert_eq!(molecule.angles().len(), 18);
        assert_eq!(molecule.dihedrals().len(), 18);

        // This is only a simple regression test on the moltype function. Feel
        // free to change the value if the molecule type algorithm change.
        assert_eq!(molecule_type(&molecule, &atoms), 2028056351119909064);
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Averages/Arithmetic_mean

// The mean is not defined for an empty list, so we must return an Option
fn mean(list: &[f64]) -> Option<f64> {
    match list.len() {
        0 => None,
        n => {
            let sum = list.iter().fold(0 as f64, |acc, &x| acc + x);
            Some(sum / n as f64)
        }
    }
}

#[cfg(not(test))]
fn main() {
    let input = vec!(3.0, 1.0, 4.0, 1.0, 5.0, 9.0);

    // This should be 3.833333
    let mean = mean(input.as_slice()).unwrap();
    println!("{}", mean);
}

#[test]
fn simple_test() {
    let vector = vec!(1.0, 2.0, 3.0, 4.0, 5.0);
    assert!(mean(vector.as_slice()).unwrap() == 3.0);
}

#[test]
fn mean_empty_list() {
    let empty_vec = vec!();
    assert!(mean(empty_vec.as_slice()).is_none());
}
<commit_msg>Use `AdditiveIterator`'s `sum()` instead of normal `fold()`.<commit_after>// Implements http://rosettacode.org/wiki/Averages/Arithmetic_mean
use std::iter::AdditiveIterator;

// The mean is not defined for an empty list, so we must return an Option
fn mean(list: &[f64]) -> Option<f64> {
    match list.len() {
        0 => None,
        n => {
            let sum = list.iter().map(|&x| x).sum();
            Some(sum / n as f64)
        }
    }
}

#[cfg(not(test))]
fn main() {
    let input = vec!(3.0, 1.0, 4.0, 1.0, 5.0, 9.0);

    // This should be 3.833333
    let mean = mean(input.as_slice()).unwrap();
    println!("{}", mean);
}

#[test]
fn simple_test() {
    let vector = vec!(1.0, 2.0, 3.0, 4.0, 5.0);
    assert!(mean(vector.as_slice()).unwrap() == 3.0);
}

#[test]
fn mean_empty_list() {
    let empty_vec = vec!();
    assert!(mean(empty_vec.as_slice()).is_none());
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;

macro_rules! parse_line_starter {
  ($line:expr, $starter:expr, $variant: ident) => {
    if $line.starts_with($starter) {
      return Some(Line::$variant(
        $line.chars()
             .skip($starter.len())
             .collect()
      ))
    }
  }
}

#[derive(Debug, PartialEq, Eq)]
pub enum Line {
    Blank,
    Divider,
    Heading1(String),
    Heading2(String),
    Heading3(String),
    Text(String),
    Quote(String),
    Decorator(String),
    UnorderedList(String),
    OrderedList(String),
}

#[derive(Debug, PartialEq, Eq)]
pub enum RawLine {
    Divider,
    Text(String),
}

#[derive(Debug)]
pub struct BlockTokenizer {
    lines: VecDeque<String>,
}

fn parse_annotation(line: &str) -> Option<Line> {
    use super::constants;

    let trimmed = line.trim();

    if line.starts_with(constants::ANNOTATION_PREFIX_TOKEN) &&
        trimmed.ends_with(constants::ANNOTATION_SUFFIX_TOKEN)
    {
        return Some(Line::Decorator(
            trimmed.chars().skip(1).take(trimmed.len() - 2).collect(),
        ));
    }

    None
}

impl BlockTokenizer {
    pub fn new<S: Into<String>>(input: S) -> Self {
        let lines = input.into().lines().map(|line| line.to_string()).collect();

        BlockTokenizer { lines }
    }

    pub fn consume_raw_line(&mut self) -> Option<RawLine> {
        match self.lines.pop_front() {
            None => None,
            Some(line) => {
                if line.starts_with("---") && line.trim().chars().all(|c| c == '-') {
                    return Some(RawLine::Divider);
                }

                Some(RawLine::Text(line))
            }
        }
    }

    pub fn consume_line(&mut self) -> Option<Line> {
        match self.consume_raw_line() {
            None => None,
            Some(RawLine::Divider) => Some(Line::Divider),
            Some(RawLine::Text(line)) => {
                if line.chars().all(char::is_whitespace) {
                    return Some(Line::Blank);
                }

                use super::constants;

                parse_line_starter!(line, constants::HEADING1_TOKEN, Heading1);
                parse_line_starter!(line, constants::HEADING2_TOKEN, Heading2);
                parse_line_starter!(line, constants::HEADING3_TOKEN, Heading3);
                parse_line_starter!(line, constants::QUOTE_TOKEN, Quote);
                parse_line_starter!(line, constants::UNORDERED_LIST_TOKEN, UnorderedList);
                parse_line_starter!(line, constants::ORDERED_LIST_TOKEN, OrderedList);

                if let Some(line) = parse_annotation(&line) {
                    return Some(line);
                }

                Some(Line::Text(line))
            }
        }
    }
}

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

    #[test]
    fn text_works() {
        let mut tokenizer = BlockTokenizer::new("hello\nworld");

        assert_eq!(tokenizer.consume_line(), Some(Line::Text("hello".into())));
        assert_eq!(tokenizer.consume_line(), Some(Line::Text("world".into())));
    }

    #[test]
    fn heading_1_works() {
        let mut tokenizer = BlockTokenizer::new("# hello\nworld");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Heading1("hello".into()))
        );
        assert_eq!(tokenizer.consume_line(), Some(Line::Text("world".into())));
    }

    #[test]
    fn heading_2_works() {
        let mut tokenizer = BlockTokenizer::new("## heading 2");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Heading2("heading 2".into()))
        );
    }

    #[test]
    fn heading_3_works() {
        let mut tokenizer = BlockTokenizer::new("### lorem ipsum");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Heading3("lorem ipsum".into()))
        );
    }

    #[test]
    fn text_with_hash_works() {
        let mut tokenizer = BlockTokenizer::new(" # lorem ipsum");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Text(" # lorem ipsum".into()))
        );
    }

    #[test]
    fn quote_works() {
        let mut tokenizer = BlockTokenizer::new("> quote\n > quote\n>quote");

        assert_eq!(tokenizer.consume_line(), Some(Line::Quote("quote".into())));
        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Text(" > quote".into()))
        );
        assert_eq!(tokenizer.consume_line(), Some(Line::Text(">quote".into())));
    }

    #[test]
    fn decorator_works() {
        let mut tokenizer = BlockTokenizer::new("[code]\n[code]   \n [code] \n  [code]  \n[code");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Decorator("code".into()))
        );
        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Decorator("code".into()))
        );
        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Text(" [code] ".into()))
        );
        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Text("  [code]  ".into()))
        );
        assert_eq!(tokenizer.consume_line(), Some(Line::Text("[code".into())));
    }

    #[test]
    fn unordered_list_works() {
        let mut tokenizer = BlockTokenizer::new("- item\n - item\n-item");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::UnorderedList("item".into()))
        );
        assert_eq!(tokenizer.consume_line(), Some(Line::Text(" - item".into())));
        assert_eq!(tokenizer.consume_line(), Some(Line::Text("-item".into())));
    }

    #[test]
    fn ordered_list_works() {
        let mut tokenizer = BlockTokenizer::new(".  item\n . item\n.item");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::OrderedList(" item".into()))
        );
        assert_eq!(tokenizer.consume_line(), Some(Line::Text(" . item".into())));
        assert_eq!(tokenizer.consume_line(), Some(Line::Text(".item".into())));
    }

    #[test]
    fn divider_works() {
        let mut tokenizer = BlockTokenizer::new("---\n------- \n--\n ---\n---foobar");

        assert_eq!(tokenizer.consume_line(), Some(Line::Divider));
        assert_eq!(tokenizer.consume_line(), Some(Line::Divider));
        assert_eq!(tokenizer.consume_line(), Some(Line::Text("--".into())));
        assert_eq!(tokenizer.consume_line(), Some(Line::Text(" ---".into())));
        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Text("---foobar".into()))
        );
    }

    #[test]
    fn empty_works() {
        let mut tokenizer = BlockTokenizer::new("   \t");

        assert_eq!(tokenizer.consume_line(), Some(Line::Blank));
    }
}
<commit_msg>Refactor into single responsible functions<commit_after>use std::collections::VecDeque;

macro_rules! parse_line_starter {
  ($line:expr, $starter:expr, $variant: ident) => {
    if $line.starts_with($starter) {
      return Some(Line::$variant(
        $line.chars()
             .skip($starter.len())
             .collect()
      ))
    }
  }
}

#[derive(Debug, PartialEq, Eq)]
pub enum Line {
    Blank,
    Divider,
    Heading1(String),
    Heading2(String),
    Heading3(String),
    Text(String),
    Quote(String),
    Decorator(String),
    UnorderedList(String),
    OrderedList(String),
}

#[derive(Debug, PartialEq, Eq)]
pub enum RawLine {
    Divider,
    Text(String),
}

#[derive(Debug)]
pub struct BlockTokenizer {
    lines: VecDeque<String>,
}

fn parse_annotation(line: &str) -> Line {
    let trimmed = line.trim();

    Line::Decorator(trimmed.chars().skip(1).take(trimmed.len() - 2).collect())
}

fn is_annotation(line: &str) -> bool {
    use super::constants;

    return line.starts_with(constants::ANNOTATION_PREFIX_TOKEN) &&
        line.trim().ends_with(constants::ANNOTATION_SUFFIX_TOKEN);
}

impl BlockTokenizer {
    pub fn new<S: Into<String>>(input: S) -> Self {
        let lines = input.into().lines().map(|line| line.to_string()).collect();

        BlockTokenizer { lines }
    }

    pub fn consume_raw_line(&mut self) -> Option<RawLine> {
        match self.lines.pop_front() {
            None => None,
            Some(line) => {
                if line.starts_with("---") && line.trim().chars().all(|c| c == '-') {
                    return Some(RawLine::Divider);
                }

                Some(RawLine::Text(line))
            }
        }
    }

    pub fn consume_line(&mut self) -> Option<Line> {
        match self.consume_raw_line() {
            None => None,
            Some(RawLine::Divider) => Some(Line::Divider),
            Some(RawLine::Text(line)) => {
                if line.chars().all(char::is_whitespace) {
                    return Some(Line::Blank);
                }

                use super::constants;

                parse_line_starter!(line, constants::HEADING1_TOKEN, Heading1);
                parse_line_starter!(line, constants::HEADING2_TOKEN, Heading2);
                parse_line_starter!(line, constants::HEADING3_TOKEN, Heading3);
                parse_line_starter!(line, constants::QUOTE_TOKEN, Quote);
                parse_line_starter!(line, constants::UNORDERED_LIST_TOKEN, UnorderedList);
                parse_line_starter!(line, constants::ORDERED_LIST_TOKEN, OrderedList);

                if is_annotation(&line) {
                    return Some(parse_annotation(&line));
                }

                Some(Line::Text(line))
            }
        }
    }
}

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

    #[test]
    fn text_works() {
        let mut tokenizer = BlockTokenizer::new("hello\nworld");

        assert_eq!(tokenizer.consume_line(), Some(Line::Text("hello".into())));
        assert_eq!(tokenizer.consume_line(), Some(Line::Text("world".into())));
    }

    #[test]
    fn heading_1_works() {
        let mut tokenizer = BlockTokenizer::new("# hello\nworld");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Heading1("hello".into()))
        );
        assert_eq!(tokenizer.consume_line(), Some(Line::Text("world".into())));
    }

    #[test]
    fn heading_2_works() {
        let mut tokenizer = BlockTokenizer::new("## heading 2");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Heading2("heading 2".into()))
        );
    }

    #[test]
    fn heading_3_works() {
        let mut tokenizer = BlockTokenizer::new("### lorem ipsum");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Heading3("lorem ipsum".into()))
        );
    }

    #[test]
    fn text_with_hash_works() {
        let mut tokenizer = BlockTokenizer::new(" # lorem ipsum");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Text(" # lorem ipsum".into()))
        );
    }

    #[test]
    fn quote_works() {
        let mut tokenizer = BlockTokenizer::new("> quote\n > quote\n>quote");

        assert_eq!(tokenizer.consume_line(), Some(Line::Quote("quote".into())));
        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Text(" > quote".into()))
        );
        assert_eq!(tokenizer.consume_line(), Some(Line::Text(">quote".into())));
    }

    #[test]
    fn decorator_works() {
        let mut tokenizer = BlockTokenizer::new("[code]\n[code]   \n [code] \n  [code]  \n[code");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Decorator("code".into()))
        );
        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Decorator("code".into()))
        );
        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Text(" [code] ".into()))
        );
        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Text("  [code]  ".into()))
        );
        assert_eq!(tokenizer.consume_line(), Some(Line::Text("[code".into())));
    }

    #[test]
    fn unordered_list_works() {
        let mut tokenizer = BlockTokenizer::new("- item\n - item\n-item");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::UnorderedList("item".into()))
        );
        assert_eq!(tokenizer.consume_line(), Some(Line::Text(" - item".into())));
        assert_eq!(tokenizer.consume_line(), Some(Line::Text("-item".into())));
    }

    #[test]
    fn ordered_list_works() {
        let mut tokenizer = BlockTokenizer::new(".  item\n . item\n.item");

        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::OrderedList(" item".into()))
        );
        assert_eq!(tokenizer.consume_line(), Some(Line::Text(" . item".into())));
        assert_eq!(tokenizer.consume_line(), Some(Line::Text(".item".into())));
    }

    #[test]
    fn divider_works() {
        let mut tokenizer = BlockTokenizer::new("---\n------- \n--\n ---\n---foobar");

        assert_eq!(tokenizer.consume_line(), Some(Line::Divider));
        assert_eq!(tokenizer.consume_line(), Some(Line::Divider));
        assert_eq!(tokenizer.consume_line(), Some(Line::Text("--".into())));
        assert_eq!(tokenizer.consume_line(), Some(Line::Text(" ---".into())));
        assert_eq!(
            tokenizer.consume_line(),
            Some(Line::Text("---foobar".into()))
        );
    }

    #[test]
    fn empty_works() {
        let mut tokenizer = BlockTokenizer::new("   \t");

        assert_eq!(tokenizer.consume_line(), Some(Line::Blank));
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

//! Implementation of cross-process surfaces for Android. This uses EGL surface.

use platform::surface::NativeSurfaceMethods;
use texturegl::Texture;

use geom::size::Size2D;
use gleam::gl::{egl_image_target_texture2d_oes, TEXTURE_2D, TexImage2D, BGRA_EXT, UNSIGNED_BYTE};
use egl::egl::EGLDisplay;
use egl::eglext::{EGLImageKHR, DestroyImageKHR};
use libc::c_void;
use std::mem;
use std::ptr;
use std::vec::Vec;

/// FIXME(Aydin Kim) :Currently, native surface is consist of 2 types of hybrid image buffer. EGLImageKHR is used to GPU rendering and vector is used to CPU rendering. EGL extension seems not provide simple way to accessing its bitmap directly. In the future, we need to find out the way to integrate them.

#[deriving(Clone)]
pub struct NativeGraphicsMetadata {
    pub display: EGLDisplay,
}

pub struct NativePaintingGraphicsContext{
    display : EGLDisplay,
}

impl NativePaintingGraphicsContext {
    pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext {
        NativePaintingGraphicsContext {
            display : metadata.display,
        }
    }
}

impl Drop for NativePaintingGraphicsContext {
    fn drop(&mut self) {}
}

pub struct NativeCompositingGraphicsContext;

impl NativeCompositingGraphicsContext {
    pub fn new() -> NativeCompositingGraphicsContext {
        NativeCompositingGraphicsContext
    }
}

pub struct NativeSurface {
    image: Option<EGLImageKHR>, // For GPU rendering
    bitmap: Option<Vec<u8>>, // For CPU rendering
    will_leak: bool,
}

impl NativeSurface {
    pub fn from_image_khr(image_khr: EGLImageKHR) -> NativeSurface {
        let mut _image: Option<EGLImageKHR> = None;
        if image_khr != ptr::null_mut() {
            _image = Some(image_khr);
        }
        NativeSurface {
            image : _image,
            bitmap: None,
            will_leak: true,
        }
    }
}

impl NativeSurfaceMethods for NativeSurface {
    /// This may only be called on the case of CPU rendering.
    fn new(_native_context: &NativePaintingGraphicsContext, size: Size2D<i32>, _stride: i32) -> NativeSurface {
        let len = size.width * size.height * 4;
        let bitmap: Vec<u8> = Vec::from_elem(len as uint, 0 as u8);

        NativeSurface {
            image: None,
            bitmap: Some(bitmap),
            will_leak : true,
        }
    }

    /// This may only be called on the compositor side.
    fn bind_to_texture(&self,
                       _native_context: &NativeCompositingGraphicsContext,
                       texture: &Texture,
                       _size: Size2D<int>) {
        let _bound = texture.bind();
        match self.image {
            None => match self.bitmap {
                Some(ref bitmap) => {
                    let data = bitmap.as_ptr() as *const c_void;
                    unsafe {
                        TexImage2D(TEXTURE_2D, 0, BGRA_EXT as i32, _size.width as i32, _size.height as i32,
                                   0, BGRA_EXT as u32, UNSIGNED_BYTE, data);
                    }
                }
                None => {
                    debug!("Cannot bind the buffer(CPU rendering), there is no bitmap");
                }
            },
            Some(image_khr) => {
                egl_image_target_texture2d_oes(TEXTURE_2D, image_khr as *const c_void);
            }
        }
    }

    /// This may only be called on the painting side.
    fn upload(&mut self, _graphics_context: &NativePaintingGraphicsContext, data: &[u8]) {
        match self.bitmap {
            Some(ref mut bitmap) => {
                unsafe {
                    bitmap.as_mut_slice().copy_memory(data);
                }
            }
            None => {
                debug!("Cannot upload the buffer(CPU rendering), there is no bitmap");
            }
        }
    }

    fn get_id(&self) -> int {
        match self.image {
            None => 0,
            Some(image_khr) => image_khr as int,
        }
    }

    fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        match self.image {
            None => {},
            Some(image_khr) => {
                DestroyImageKHR(graphics_context.display, image_khr);
                mem::replace(&mut self.image, None);
            }
        }
        self.mark_wont_leak()
    }

    fn mark_will_leak(&mut self) {
        self.will_leak = true
    }
    fn mark_wont_leak(&mut self) {
        self.will_leak = false
    }
}
<commit_msg>Rust update for Android<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

//! Implementation of cross-process surfaces for Android. This uses EGL surface.

use platform::surface::NativeSurfaceMethods;
use texturegl::Texture;

use geom::size::Size2D;
use gleam::gl::{egl_image_target_texture2d_oes, TEXTURE_2D, TexImage2D, BGRA_EXT, UNSIGNED_BYTE};
use egl::egl::EGLDisplay;
use egl::eglext::{EGLImageKHR, DestroyImageKHR};
use libc::c_void;
use std::mem;
use std::ptr;
use std::slice::bytes::copy_memory;
use std::vec::Vec;

/// FIXME(Aydin Kim) :Currently, native surface is consist of 2 types of hybrid image buffer. EGLImageKHR is used to GPU rendering and vector is used to CPU rendering. EGL extension seems not provide simple way to accessing its bitmap directly. In the future, we need to find out the way to integrate them.

#[deriving(Clone)]
pub struct NativeGraphicsMetadata {
    pub display: EGLDisplay,
}

pub struct NativePaintingGraphicsContext{
    display : EGLDisplay,
}

impl NativePaintingGraphicsContext {
    pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext {
        NativePaintingGraphicsContext {
            display : metadata.display,
        }
    }
}

impl Drop for NativePaintingGraphicsContext {
    fn drop(&mut self) {}
}

pub struct NativeCompositingGraphicsContext;

impl NativeCompositingGraphicsContext {
    pub fn new() -> NativeCompositingGraphicsContext {
        NativeCompositingGraphicsContext
    }
}

pub struct NativeSurface {
    image: Option<EGLImageKHR>, // For GPU rendering
    bitmap: Option<Vec<u8>>, // For CPU rendering
    will_leak: bool,
}

impl NativeSurface {
    pub fn from_image_khr(image_khr: EGLImageKHR) -> NativeSurface {
        let mut _image: Option<EGLImageKHR> = None;
        if image_khr != ptr::null_mut() {
            _image = Some(image_khr);
        }
        NativeSurface {
            image : _image,
            bitmap: None,
            will_leak: true,
        }
    }
}

impl NativeSurfaceMethods for NativeSurface {
    /// This may only be called on the case of CPU rendering.
    fn new(_native_context: &NativePaintingGraphicsContext, size: Size2D<i32>, _stride: i32) -> NativeSurface {
        let len = size.width * size.height * 4;
        let bitmap: Vec<u8> = Vec::from_elem(len as uint, 0 as u8);

        NativeSurface {
            image: None,
            bitmap: Some(bitmap),
            will_leak : true,
        }
    }

    /// This may only be called on the compositor side.
    fn bind_to_texture(&self,
                       _native_context: &NativeCompositingGraphicsContext,
                       texture: &Texture,
                       _size: Size2D<int>) {
        let _bound = texture.bind();
        match self.image {
            None => match self.bitmap {
                Some(ref bitmap) => {
                    let data = bitmap.as_ptr() as *const c_void;
                    unsafe {
                        TexImage2D(TEXTURE_2D, 0, BGRA_EXT as i32, _size.width as i32, _size.height as i32,
                                   0, BGRA_EXT as u32, UNSIGNED_BYTE, data);
                    }
                }
                None => {
                    debug!("Cannot bind the buffer(CPU rendering), there is no bitmap");
                }
            },
            Some(image_khr) => {
                egl_image_target_texture2d_oes(TEXTURE_2D, image_khr as *const c_void);
            }
        }
    }

    /// This may only be called on the painting side.
    fn upload(&mut self, _graphics_context: &NativePaintingGraphicsContext, data: &[u8]) {
        match self.bitmap {
            Some(ref mut bitmap) => {
                copy_memory(bitmap.as_mut_slice(), data);
            }
            None => {
                debug!("Cannot upload the buffer(CPU rendering), there is no bitmap");
            }
        }
    }

    fn get_id(&self) -> int {
        match self.image {
            None => 0,
            Some(image_khr) => image_khr as int,
        }
    }

    fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        match self.image {
            None => {},
            Some(image_khr) => {
                DestroyImageKHR(graphics_context.display, image_khr);
                mem::replace(&mut self.image, None);
            }
        }
        self.mark_wont_leak()
    }

    fn mark_will_leak(&mut self) {
        self.will_leak = true
    }
    fn mark_wont_leak(&mut self) {
        self.will_leak = false
    }
}
<|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.

//! Sampling from random distributions.
//!
//! This is a generalization of `Rand` to allow parameters to control the
//! exact properties of the generated values, e.g. the mean and standard
//! deviation of a normal distribution. The `Sample` trait is the most
//! general, and allows for generating values that change some state
//! internally. The `IndependentSample` trait is for generating values
//! that do not need to record state.

use std::num::{Float, Int};
use std::marker;

use {Rng, Rand};

pub use self::range::Range;
pub use self::gamma::{Gamma, ChiSquared, FisherF, StudentT};
pub use self::normal::{Normal, LogNormal};
pub use self::exponential::Exp;

pub mod range;
pub mod gamma;
pub mod normal;
pub mod exponential;

/// Types that can be used to create a random instance of `Support`.
pub trait Sample<Support> {
    /// Generate a random value of `Support`, using `rng` as the
    /// source of randomness.
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Support;
}

/// `Sample`s that do not require keeping track of state.
///
/// Since no state is recorded, each sample is (statistically)
/// independent of all others, assuming the `Rng` used has this
/// property.
// FIXME maybe having this separate is overkill (the only reason is to
// take &self rather than &mut self)? or maybe this should be the
// trait called `Sample` and the other should be `DependentSample`.
pub trait IndependentSample<Support>: Sample<Support> {
    /// Generate a random value.
    fn ind_sample<R: Rng>(&self, &mut R) -> Support;
}

/// A wrapper for generating types that implement `Rand` via the
/// `Sample` & `IndependentSample` traits.
pub struct RandSample<Sup> {
    _marker: marker::PhantomData<fn() -> Sup>,
}

impl<Sup> Copy for RandSample<Sup> {}

impl<Sup: Rand> Sample<Sup> for RandSample<Sup> {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
}

impl<Sup: Rand> IndependentSample<Sup> for RandSample<Sup> {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
        rng.gen()
    }
}

impl<Sup> RandSample<Sup> {
    pub fn new() -> RandSample<Sup> {
        RandSample { _marker: marker::PhantomData }
    }
}

/// A value with a particular weight for use with `WeightedChoice`.
#[derive(Copy)]
pub struct Weighted<T> {
    /// The numerical weight of this item
    pub weight: u32,
    /// The actual item which is being weighted
    pub item: T,
}

/// A distribution that selects from a finite collection of weighted items.
///
/// Each item has an associated weight that influences how likely it
/// is to be chosen: higher weight is more likely.
///
/// The `Clone` restriction is a limitation of the `Sample` and
/// `IndependentSample` traits. Note that `&T` is (cheaply) `Clone` for
/// all `T`, as is `u32`, so one can store references or indices into
/// another vector.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{Weighted, WeightedChoice, IndependentSample};
///
/// let mut items = vec!(Weighted { weight: 2, item: 'a' },
///                      Weighted { weight: 4, item: 'b' },
///                      Weighted { weight: 1, item: 'c' });
/// let wc = WeightedChoice::new(items.as_mut_slice());
/// let mut rng = rand::thread_rng();
/// for _ in 0..16 {
///      // on average prints 'a' 4 times, 'b' 8 and 'c' twice.
///      println!("{}", wc.ind_sample(&mut rng));
/// }
/// ```
pub struct WeightedChoice<'a, T:'a> {
    items: &'a mut [Weighted<T>],
    weight_range: Range<u32>
}

impl<'a, T: Clone> WeightedChoice<'a, T> {
    /// Create a new `WeightedChoice`.
    ///
    /// Panics if:
    /// - `v` is empty
    /// - the total weight is 0
    /// - the total weight is larger than a `u32` can contain.
    pub fn new(items: &'a mut [Weighted<T>]) -> WeightedChoice<'a, T> {
        // strictly speaking, this is subsumed by the total weight == 0 case
        assert!(!items.is_empty(), "WeightedChoice::new called with no items");

        let mut running_total = 0;

        // we convert the list from individual weights to cumulative
        // weights so we can binary search. This *could* drop elements
        // with weight == 0 as an optimisation.
        for item in items.iter_mut() {
            running_total = match running_total.checked_add(item.weight) {
                Some(n) => n,
                None => panic!("WeightedChoice::new called with a total weight \
                               larger than a u32 can contain")
            };

            item.weight = running_total;
        }
        assert!(running_total != 0, "WeightedChoice::new called with a total weight of 0");

        WeightedChoice {
            items: items,
            // we're likely to be generating numbers in this range
            // relatively often, so might as well cache it
            weight_range: Range::new(0, running_total)
        }
    }
}

impl<'a, T: Clone> Sample<T> for WeightedChoice<'a, T> {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> T { self.ind_sample(rng) }
}

impl<'a, T: Clone> IndependentSample<T> for WeightedChoice<'a, T> {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> T {
        // we want to find the first element that has cumulative
        // weight > sample_weight, which we do by binary since the
        // cumulative weights of self.items are sorted.

        // choose a weight in [0, total_weight)
        let sample_weight = self.weight_range.ind_sample(rng);

        // short circuit when it's the first item
        if sample_weight < self.items[0].weight {
            return self.items[0].item.clone();
        }

        let mut idx = 0;
        let mut modifier = self.items.len();

        // now we know that every possibility has an element to the
        // left, so we can just search for the last element that has
        // cumulative weight <= sample_weight, then the next one will
        // be "it". (Note that this greatest element will never be the
        // last element of the vector, since sample_weight is chosen
        // in [0, total_weight) and the cumulative weight of the last
        // one is exactly the total weight.)
        while modifier > 1 {
            let i = idx + modifier / 2;
            if self.items[i].weight <= sample_weight {
                // we're small, so look to the right, but allow this
                // exact element still.
                idx = i;
                // we need the `/ 2` to round up otherwise we'll drop
                // the trailing elements when `modifier` is odd.
                modifier += 1;
            } else {
                // otherwise we're too big, so go left. (i.e. do
                // nothing)
            }
            modifier /= 2;
        }
        return self.items[idx + 1].item.clone();
    }
}

mod ziggurat_tables;

/// Sample a random number using the Ziggurat method (specifically the
/// ZIGNOR variant from Doornik 2005). Most of the arguments are
/// directly from the paper:
///
/// * `rng`: source of randomness
/// * `symmetric`: whether this is a symmetric distribution, or one-sided with P(x < 0) = 0.
/// * `X`: the $x_i$ abscissae.
/// * `F`: precomputed values of the PDF at the $x_i$, (i.e. $f(x_i)$)
/// * `F_DIFF`: precomputed values of $f(x_i) - f(x_{i+1})$
/// * `pdf`: the probability density function
/// * `zero_case`: manual sampling from the tail when we chose the
///    bottom box (i.e. i == 0)

// the perf improvement (25-50%) is definitely worth the extra code
// size from force-inlining.
#[inline(always)]
fn ziggurat<R: Rng, P, Z>(
            rng: &mut R,
            symmetric: bool,
            x_tab: ziggurat_tables::ZigTable,
            f_tab: ziggurat_tables::ZigTable,
            mut pdf: P,
            mut zero_case: Z)
            -> f64 where P: FnMut(f64) -> f64, Z: FnMut(&mut R, f64) -> f64 {
    const SCALE: f64 = (1u64 << 53) as f64;
    loop {
        // reimplement the f64 generation as an optimisation suggested
        // by the Doornik paper: we have a lot of precision-space
        // (i.e. there are 11 bits of the 64 of a u64 to use after
        // creating a f64), so we might as well reuse some to save
        // generating a whole extra random number. (Seems to be 15%
        // faster.)
        //
        // This unfortunately misses out on the benefits of direct
        // floating point generation if an RNG like dSMFT is
        // used. (That is, such RNGs create floats directly, highly
        // efficiently and overload next_f32/f64, so by not calling it
        // this may be slower than it would be otherwise.)
        // FIXME: investigate/optimise for the above.
        let bits: u64 = rng.gen();
        let i = (bits & 0xff) as usize;
        let f = (bits >> 11) as f64 / SCALE;

        // u is either U(-1, 1) or U(0, 1) depending on if this is a
        // symmetric distribution or not.
        let u = if symmetric {2.0 * f - 1.0} else {f};
        let x = u * x_tab[i];

        let test_x = if symmetric { x.abs() } else {x};

        // algebraically equivalent to |u| < x_tab[i+1]/x_tab[i] (or u < x_tab[i+1]/x_tab[i])
        if test_x < x_tab[i + 1] {
            return x;
        }
        if i == 0 {
            return zero_case(rng, u);
        }
        // algebraically equivalent to f1 + DRanU()*(f0 - f1) < 1
        if f_tab[i + 1] + (f_tab[i] - f_tab[i + 1]) * rng.gen() < pdf(x) {
            return x;
        }
    }
}

#[cfg(test)]
mod tests {

    use {Rng, Rand};
    use super::{RandSample, WeightedChoice, Weighted, Sample, IndependentSample};

    #[derive(PartialEq, Debug)]
    struct ConstRand(usize);
    impl Rand for ConstRand {
        fn rand<R: Rng>(_: &mut R) -> ConstRand {
            ConstRand(0)
        }
    }

    // 0, 1, 2, 3, ...
    struct CountingRng { i: u32 }
    impl Rng for CountingRng {
        fn next_u32(&mut self) -> u32 {
            self.i += 1;
            self.i - 1
        }
        fn next_u64(&mut self) -> u64 {
            self.next_u32() as u64
        }
    }

    #[test]
    fn test_rand_sample() {
        let mut rand_sample = RandSample::<ConstRand>::new();

        assert_eq!(rand_sample.sample(&mut ::test::rng()), ConstRand(0));
        assert_eq!(rand_sample.ind_sample(&mut ::test::rng()), ConstRand(0));
    }
    #[test]
    fn test_weighted_choice() {
        // this makes assumptions about the internal implementation of
        // WeightedChoice, specifically: it doesn't reorder the items,
        // it doesn't do weird things to the RNG (so 0 maps to 0, 1 to
        // 1, internally; modulo a modulo operation).

        macro_rules! t {
            ($items:expr, $expected:expr) => {{
                let mut items = $items;
                let wc = WeightedChoice::new(items.as_mut_slice());
                let expected = $expected;

                let mut rng = CountingRng { i: 0 };

                for &val in expected.iter() {
                    assert_eq!(wc.ind_sample(&mut rng), val)
                }
            }}
        }

        t!(vec!(Weighted { weight: 1, item: 10}), [10]);

        // skip some
        t!(vec!(Weighted { weight: 0, item: 20},
                Weighted { weight: 2, item: 21},
                Weighted { weight: 0, item: 22},
                Weighted { weight: 1, item: 23}),
           [21,21, 23]);

        // different weights
        t!(vec!(Weighted { weight: 4, item: 30},
                Weighted { weight: 3, item: 31}),
           [30,30,30,30, 31,31,31]);

        // check that we're binary searching
        // correctly with some vectors of odd
        // length.
        t!(vec!(Weighted { weight: 1, item: 40},
                Weighted { weight: 1, item: 41},
                Weighted { weight: 1, item: 42},
                Weighted { weight: 1, item: 43},
                Weighted { weight: 1, item: 44}),
           [40, 41, 42, 43, 44]);
        t!(vec!(Weighted { weight: 1, item: 50},
                Weighted { weight: 1, item: 51},
                Weighted { weight: 1, item: 52},
                Weighted { weight: 1, item: 53},
                Weighted { weight: 1, item: 54},
                Weighted { weight: 1, item: 55},
                Weighted { weight: 1, item: 56}),
           [50, 51, 52, 53, 54, 55, 56]);
    }

    #[test] #[should_panic]
    fn test_weighted_choice_no_items() {
        WeightedChoice::<isize>::new(&mut []);
    }
    #[test] #[should_panic]
    fn test_weighted_choice_zero_weight() {
        WeightedChoice::new(&mut [Weighted { weight: 0, item: 0},
                                  Weighted { weight: 0, item: 1}]);
    }
    #[test] #[should_panic]
    fn test_weighted_choice_weight_overflows() {
        let x = !0 / 2; // x + x + 2 is the overflow
        WeightedChoice::new(&mut [Weighted { weight: x, item: 0 },
                                  Weighted { weight: 1, item: 1 },
                                  Weighted { weight: x, item: 2 },
                                  Weighted { weight: 1, item: 3 }]);
    }
}
<commit_msg>Implemented Clone trait on Weighted struct to allow cloning of weighted choices<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.

//! Sampling from random distributions.
//!
//! This is a generalization of `Rand` to allow parameters to control the
//! exact properties of the generated values, e.g. the mean and standard
//! deviation of a normal distribution. The `Sample` trait is the most
//! general, and allows for generating values that change some state
//! internally. The `IndependentSample` trait is for generating values
//! that do not need to record state.

use std::num::{Float, Int};
use std::marker;

use {Rng, Rand};

pub use self::range::Range;
pub use self::gamma::{Gamma, ChiSquared, FisherF, StudentT};
pub use self::normal::{Normal, LogNormal};
pub use self::exponential::Exp;

pub mod range;
pub mod gamma;
pub mod normal;
pub mod exponential;

/// Types that can be used to create a random instance of `Support`.
pub trait Sample<Support> {
    /// Generate a random value of `Support`, using `rng` as the
    /// source of randomness.
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Support;
}

/// `Sample`s that do not require keeping track of state.
///
/// Since no state is recorded, each sample is (statistically)
/// independent of all others, assuming the `Rng` used has this
/// property.
// FIXME maybe having this separate is overkill (the only reason is to
// take &self rather than &mut self)? or maybe this should be the
// trait called `Sample` and the other should be `DependentSample`.
pub trait IndependentSample<Support>: Sample<Support> {
    /// Generate a random value.
    fn ind_sample<R: Rng>(&self, &mut R) -> Support;
}

/// A wrapper for generating types that implement `Rand` via the
/// `Sample` & `IndependentSample` traits.
pub struct RandSample<Sup> {
    _marker: marker::PhantomData<fn() -> Sup>,
}

impl<Sup> Copy for RandSample<Sup> {}

impl<Sup: Rand> Sample<Sup> for RandSample<Sup> {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
}

impl<Sup: Rand> IndependentSample<Sup> for RandSample<Sup> {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
        rng.gen()
    }
}

impl<Sup> RandSample<Sup> {
    pub fn new() -> RandSample<Sup> {
        RandSample { _marker: marker::PhantomData }
    }
}

/// A value with a particular weight for use with `WeightedChoice`.
#[derive(Copy)]
pub struct Weighted<T> {
    /// The numerical weight of this item
    pub weight: u32,
    /// The actual item which is being weighted
    pub item: T,
}

//implementation of Clone for Weighted
impl<T> Clone for Weighted<T> where T:Clone{
    fn clone(&self) -> Self {
        Weighted {
            weight: self.weight.clone(),
            item: self.item.clone()
        }
    }
    fn clone_from(&mut self, source: &Self) {
        self.weight = source.weight.clone();
        self.item = source.item.clone();
    }
}

/// A distribution that selects from a finite collection of weighted items.
///
/// Each item has an associated weight that influences how likely it
/// is to be chosen: higher weight is more likely.
///
/// The `Clone` restriction is a limitation of the `Sample` and
/// `IndependentSample` traits. Note that `&T` is (cheaply) `Clone` for
/// all `T`, as is `u32`, so one can store references or indices into
/// another vector.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{Weighted, WeightedChoice, IndependentSample};
///
/// let mut items = vec!(Weighted { weight: 2, item: 'a' },
///                      Weighted { weight: 4, item: 'b' },
///                      Weighted { weight: 1, item: 'c' });
/// let wc = WeightedChoice::new(items.as_mut_slice());
/// let mut rng = rand::thread_rng();
/// for _ in 0..16 {
///      // on average prints 'a' 4 times, 'b' 8 and 'c' twice.
///      println!("{}", wc.ind_sample(&mut rng));
/// }
/// ```
pub struct WeightedChoice<'a, T:'a> {
    items: &'a mut [Weighted<T>],
    weight_range: Range<u32>
}

impl<'a, T: Clone> WeightedChoice<'a, T> {
    /// Create a new `WeightedChoice`.
    ///
    /// Panics if:
    /// - `v` is empty
    /// - the total weight is 0
    /// - the total weight is larger than a `u32` can contain.
    pub fn new(items: &'a mut [Weighted<T>]) -> WeightedChoice<'a, T> {
        // strictly speaking, this is subsumed by the total weight == 0 case
        assert!(!items.is_empty(), "WeightedChoice::new called with no items");

        let mut running_total = 0;

        // we convert the list from individual weights to cumulative
        // weights so we can binary search. This *could* drop elements
        // with weight == 0 as an optimisation.
        for item in items.iter_mut() {
            running_total = match running_total.checked_add(item.weight) {
                Some(n) => n,
                None => panic!("WeightedChoice::new called with a total weight \
                               larger than a u32 can contain")
            };

            item.weight = running_total;
        }
        assert!(running_total != 0, "WeightedChoice::new called with a total weight of 0");

        WeightedChoice {
            items: items,
            // we're likely to be generating numbers in this range
            // relatively often, so might as well cache it
            weight_range: Range::new(0, running_total)
        }
    }
}

impl<'a, T: Clone> Sample<T> for WeightedChoice<'a, T> {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> T { self.ind_sample(rng) }
}

impl<'a, T: Clone> IndependentSample<T> for WeightedChoice<'a, T> {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> T {
        // we want to find the first element that has cumulative
        // weight > sample_weight, which we do by binary since the
        // cumulative weights of self.items are sorted.

        // choose a weight in [0, total_weight)
        let sample_weight = self.weight_range.ind_sample(rng);

        // short circuit when it's the first item
        if sample_weight < self.items[0].weight {
            return self.items[0].item.clone();
        }

        let mut idx = 0;
        let mut modifier = self.items.len();

        // now we know that every possibility has an element to the
        // left, so we can just search for the last element that has
        // cumulative weight <= sample_weight, then the next one will
        // be "it". (Note that this greatest element will never be the
        // last element of the vector, since sample_weight is chosen
        // in [0, total_weight) and the cumulative weight of the last
        // one is exactly the total weight.)
        while modifier > 1 {
            let i = idx + modifier / 2;
            if self.items[i].weight <= sample_weight {
                // we're small, so look to the right, but allow this
                // exact element still.
                idx = i;
                // we need the `/ 2` to round up otherwise we'll drop
                // the trailing elements when `modifier` is odd.
                modifier += 1;
            } else {
                // otherwise we're too big, so go left. (i.e. do
                // nothing)
            }
            modifier /= 2;
        }
        return self.items[idx + 1].item.clone();
    }
}

mod ziggurat_tables;

/// Sample a random number using the Ziggurat method (specifically the
/// ZIGNOR variant from Doornik 2005). Most of the arguments are
/// directly from the paper:
///
/// * `rng`: source of randomness
/// * `symmetric`: whether this is a symmetric distribution, or one-sided with P(x < 0) = 0.
/// * `X`: the $x_i$ abscissae.
/// * `F`: precomputed values of the PDF at the $x_i$, (i.e. $f(x_i)$)
/// * `F_DIFF`: precomputed values of $f(x_i) - f(x_{i+1})$
/// * `pdf`: the probability density function
/// * `zero_case`: manual sampling from the tail when we chose the
///    bottom box (i.e. i == 0)

// the perf improvement (25-50%) is definitely worth the extra code
// size from force-inlining.
#[inline(always)]
fn ziggurat<R: Rng, P, Z>(
            rng: &mut R,
            symmetric: bool,
            x_tab: ziggurat_tables::ZigTable,
            f_tab: ziggurat_tables::ZigTable,
            mut pdf: P,
            mut zero_case: Z)
            -> f64 where P: FnMut(f64) -> f64, Z: FnMut(&mut R, f64) -> f64 {
    const SCALE: f64 = (1u64 << 53) as f64;
    loop {
        // reimplement the f64 generation as an optimisation suggested
        // by the Doornik paper: we have a lot of precision-space
        // (i.e. there are 11 bits of the 64 of a u64 to use after
        // creating a f64), so we might as well reuse some to save
        // generating a whole extra random number. (Seems to be 15%
        // faster.)
        //
        // This unfortunately misses out on the benefits of direct
        // floating point generation if an RNG like dSMFT is
        // used. (That is, such RNGs create floats directly, highly
        // efficiently and overload next_f32/f64, so by not calling it
        // this may be slower than it would be otherwise.)
        // FIXME: investigate/optimise for the above.
        let bits: u64 = rng.gen();
        let i = (bits & 0xff) as usize;
        let f = (bits >> 11) as f64 / SCALE;

        // u is either U(-1, 1) or U(0, 1) depending on if this is a
        // symmetric distribution or not.
        let u = if symmetric {2.0 * f - 1.0} else {f};
        let x = u * x_tab[i];

        let test_x = if symmetric { x.abs() } else {x};

        // algebraically equivalent to |u| < x_tab[i+1]/x_tab[i] (or u < x_tab[i+1]/x_tab[i])
        if test_x < x_tab[i + 1] {
            return x;
        }
        if i == 0 {
            return zero_case(rng, u);
        }
        // algebraically equivalent to f1 + DRanU()*(f0 - f1) < 1
        if f_tab[i + 1] + (f_tab[i] - f_tab[i + 1]) * rng.gen() < pdf(x) {
            return x;
        }
    }
}

#[cfg(test)]
mod tests {

    use {Rng, Rand};
    use super::{RandSample, WeightedChoice, Weighted, Sample, IndependentSample};

    #[derive(PartialEq, Debug)]
    struct ConstRand(usize);
    impl Rand for ConstRand {
        fn rand<R: Rng>(_: &mut R) -> ConstRand {
            ConstRand(0)
        }
    }

    // 0, 1, 2, 3, ...
    struct CountingRng { i: u32 }
    impl Rng for CountingRng {
        fn next_u32(&mut self) -> u32 {
            self.i += 1;
            self.i - 1
        }
        fn next_u64(&mut self) -> u64 {
            self.next_u32() as u64
        }
    }

    #[test]
    fn test_rand_sample() {
        let mut rand_sample = RandSample::<ConstRand>::new();

        assert_eq!(rand_sample.sample(&mut ::test::rng()), ConstRand(0));
        assert_eq!(rand_sample.ind_sample(&mut ::test::rng()), ConstRand(0));
    }
    #[test]
    fn test_weighted_choice() {
        // this makes assumptions about the internal implementation of
        // WeightedChoice, specifically: it doesn't reorder the items,
        // it doesn't do weird things to the RNG (so 0 maps to 0, 1 to
        // 1, internally; modulo a modulo operation).

        macro_rules! t {
            ($items:expr, $expected:expr) => {{
                let mut items = $items;
                let wc = WeightedChoice::new(items.as_mut_slice());
                let expected = $expected;

                let mut rng = CountingRng { i: 0 };

                for &val in expected.iter() {
                    assert_eq!(wc.ind_sample(&mut rng), val)
                }
            }}
        }

        t!(vec!(Weighted { weight: 1, item: 10}), [10]);

        // skip some
        t!(vec!(Weighted { weight: 0, item: 20},
                Weighted { weight: 2, item: 21},
                Weighted { weight: 0, item: 22},
                Weighted { weight: 1, item: 23}),
           [21,21, 23]);

        // different weights
        t!(vec!(Weighted { weight: 4, item: 30},
                Weighted { weight: 3, item: 31}),
           [30,30,30,30, 31,31,31]);

        // check that we're binary searching
        // correctly with some vectors of odd
        // length.
        t!(vec!(Weighted { weight: 1, item: 40},
                Weighted { weight: 1, item: 41},
                Weighted { weight: 1, item: 42},
                Weighted { weight: 1, item: 43},
                Weighted { weight: 1, item: 44}),
           [40, 41, 42, 43, 44]);
        t!(vec!(Weighted { weight: 1, item: 50},
                Weighted { weight: 1, item: 51},
                Weighted { weight: 1, item: 52},
                Weighted { weight: 1, item: 53},
                Weighted { weight: 1, item: 54},
                Weighted { weight: 1, item: 55},
                Weighted { weight: 1, item: 56}),
           [50, 51, 52, 53, 54, 55, 56]);
    }

    #[test] #[should_panic]
    fn test_weighted_choice_no_items() {
        WeightedChoice::<isize>::new(&mut []);
    }
    #[test] #[should_panic]
    fn test_weighted_choice_zero_weight() {
        WeightedChoice::new(&mut [Weighted { weight: 0, item: 0},
                                  Weighted { weight: 0, item: 1}]);
    }
    #[test] #[should_panic]
    fn test_weighted_choice_weight_overflows() {
        let x = !0 / 2; // x + x + 2 is the overflow
        WeightedChoice::new(&mut [Weighted { weight: x, item: 0 },
                                  Weighted { weight: 1, item: 1 },
                                  Weighted { weight: x, item: 2 },
                                  Weighted { weight: 1, item: 3 }]);
    }
}
<|endoftext|>


<commit_before>//! This module shows an example of code generated by the macro. **IT MUST NOT BE USED OUTSIDE THIS
//! CRATE**.

bitflags! {
    /// This is the same `Flags` struct defined in the [crate level example](../index.html#example).
    /// Note that this struct is just for documentation purposes only, it must not be used outside
    /// this crate.
    pub struct Flags: u32 {
        const A = 0b00000001;
        const B = 0b00000010;
        const C = 0b00000100;
        const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
    }
}
<commit_msg>fix up example generated module<commit_after>//! This module shows an example of code generated by the macro. **IT MUST NOT BE USED OUTSIDE THIS
//! CRATE**.

bitflags! {
    /// This is the same `Flags` struct defined in the [crate level example](../index.html#example).
    /// Note that this struct is just for documentation purposes only, it must not be used outside
    /// this crate.
    pub struct Flags: u32 {
        const A = 0b00000001;
        const B = 0b00000010;
        const C = 0b00000100;
        const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
    }
}
<|endoftext|>


<commit_before>mod command;
mod configuration;

pub use self::command::Command;
pub use self::configuration::Configuration;

use self::command::InternalCommand;
use std::collections::HashMap;
use std::sync::Arc;
use std::thread;
use ::client::Context;
use ::model::Message;

#[allow(type_complexity)]
#[derive(Default)]
pub struct Framework {
    configuration: Configuration,
    commands: HashMap<String, InternalCommand>,
    checks: HashMap<String, Arc<Fn(&Context, &Message) -> bool + Send + Sync + 'static>>,
    pub initialized: bool,
}

impl Framework {
    pub fn configure<F>(mut self, f: F) -> Self
        where F: FnOnce(Configuration) -> Configuration {
        self.configuration = f(self.configuration);
        self.initialized = true;

        self
    }

    #[doc(hidden)]
    pub fn dispatch(&mut self, context: Context, message: Message) {
        // Determine the point at which the prefix ends, and the command starts.
        let pos = if let Some(ref prefix) = self.configuration.prefix {
            let mut mention_ends = None;

            if let Some(ref mentions) = self.configuration.on_mention {
                for mention in mentions {
                    if !message.content.starts_with(&mention[..]) {
                        continue;
                    }

                    mention_ends = Some(mention.len() + 1);

                    break;
                }
            }

            if let Some(mention_ends) = mention_ends {
                mention_ends
            } else if !message.content.starts_with(prefix) {
                return;
            } else {
                prefix.len()
            }
        } else {
            0
        };

        // Ensure that the message length is at least longer than the prefix
        // length. There's no point in checking further ahead if there's nothing
        // to check.
        if message.content.len() <= pos {
            return;
        }

        let mut built = String::new();

        for i in 0..self.configuration.depth {
            if i > 0 {
                built.push(' ');
            }

            built.push_str(match {
                message.content
                    .split_at(pos)
                    .1
                    .split_whitespace()
                    .collect::<Vec<&str>>()
                    .get(i)
            } {
                Some(piece) => piece,
                None => return,
            });

            if let Some(command) = self.commands.get(&built) {
                if let Some(check) = self.checks.get(&built) {
                    if !(check)(&context, &message) {
                        return;
                    }
                }

                let command = command.clone();

                thread::spawn(move || {
                    (command)(context, message)
                });

                return;
            }
        }
    }

    pub fn on<F, S>(mut self, command_name: S, f: F) -> Self
        where F: Fn(Context, Message) + Send + Sync + 'static,
              S: Into<String> {
        self.commands.insert(command_name.into(), Arc::new(f));
        self.initialized = true;

        self
    }

    pub fn set_check<F, S>(mut self, command: S, check: F) -> Self
        where F: Fn(&Context, &Message) -> bool + Send + Sync + 'static,
              S: Into<String> {
        self.checks.insert(command.into(), Arc::new(check));
        self.initialized = true;

        self
    }
}
<commit_msg>Allow non-prefixed mentions<commit_after>mod command;
mod configuration;

pub use self::command::Command;
pub use self::configuration::Configuration;

use self::command::InternalCommand;
use std::collections::HashMap;
use std::sync::Arc;
use std::thread;
use ::client::Context;
use ::model::Message;

#[allow(type_complexity)]
#[derive(Default)]
pub struct Framework {
    configuration: Configuration,
    commands: HashMap<String, InternalCommand>,
    checks: HashMap<String, Arc<Fn(&Context, &Message) -> bool + Send + Sync + 'static>>,
    pub initialized: bool,
}

impl Framework {
    pub fn configure<F>(mut self, f: F) -> Self
        where F: FnOnce(Configuration) -> Configuration {
        self.configuration = f(self.configuration);
        self.initialized = true;

        self
    }

    #[doc(hidden)]
    pub fn dispatch(&mut self, context: Context, message: Message) {
        // Determine the point at which the prefix ends, and the command starts.
        let pos = if let Some(ref prefix) = self.configuration.prefix {
            if let Some(mention_ends) = self.find_mention_end(&message.content) {
                mention_ends
            } else if !message.content.starts_with(prefix) {
                return;
            } else {
                prefix.len()
            }
        } else if self.configuration.on_mention.is_some() {
            match self.find_mention_end(&message.content) {
                Some(mention_end) => mention_end,
                None => return,
            }
        } else {
            0
        };

        // Ensure that the message length is at least longer than the prefix
        // length. There's no point in checking further ahead if there's nothing
        // to check.
        if message.content.len() <= pos {
            return;
        }

        let mut built = String::new();

        for i in 0..self.configuration.depth {
            if i > 0 {
                built.push(' ');
            }

            built.push_str(match {
                message.content
                    .split_at(pos)
                    .1
                    .split_whitespace()
                    .collect::<Vec<&str>>()
                    .get(i)
            } {
                Some(piece) => piece,
                None => return,
            });

            if let Some(command) = self.commands.get(&built) {
                if let Some(check) = self.checks.get(&built) {
                    if !(check)(&context, &message) {
                        return;
                    }
                }

                let command = command.clone();

                thread::spawn(move || {
                    (command)(context, message)
                });

                return;
            }
        }
    }

    pub fn on<F, S>(mut self, command_name: S, f: F) -> Self
        where F: Fn(Context, Message) + Send + Sync + 'static,
              S: Into<String> {
        self.commands.insert(command_name.into(), Arc::new(f));
        self.initialized = true;

        self
    }

    pub fn set_check<F, S>(mut self, command: S, check: F) -> Self
        where F: Fn(&Context, &Message) -> bool + Send + Sync + 'static,
              S: Into<String> {
        self.checks.insert(command.into(), Arc::new(check));
        self.initialized = true;

        self
    }

    fn find_mention_end(&self, content: &str) -> Option<usize> {
        if let Some(ref mentions) = self.configuration.on_mention {
            for mention in mentions {
                if !content.starts_with(&mention[..]) {
                    continue;
                }

                return Some(mention.len() + 1);
            }
        }

        None
    }
}
<|endoftext|>