<commit_before>use std::io::Write;
use std::os::unix::process::CommandExt;
use std::process::Command;

const SYSTEMD_RUN: &'static str = "/usr/bin/systemd-run";
const FIREJAIL: &'static str = "/usr/bin/firejail";

const FIREFOX: &'static str = "/usr/bin/firefox";
const FIREFOX_PROFILE: &'static str = "/etc/firejail/firefox.profile";
const FIREFOX_MOZILLA_SFW_PROFILE: &'static str = "default-1473025815439";

const FIREFOX_MEMORY_HIGH: i32 = 4420;
const FIREFOX_MEMORY_MAX: i32 = 5200;

const KEIRA: &'static str = "/home/kalvin/Downloads/.firefox-nightly/firefox";
const KEIRA_PROFILE: &'static str = "/etc/firejail/firefox-nightly.profile";

const TERM: &'static str = "/usr/bin/alacritty";
const TERM_PROFILE: &'static str = "/etc/firejail/x-terminal-emulator.profile";

const THUNDERBIRD: &'static str = "/home/kalvin/Downloads/.thunderbird-beta/thunderbird";
const THUNDERBIRD_PROFILE: &'static str = "/etc/firejail/thunderbird-beta.profile";

const QUODLIBET_FIFO: &'static str = "/home/kalvin/.config/quodlibet/control";

#[derive(Debug)]
struct CgroupedFirejailedCommandOptions<'a> {
    bin_path: &'a str,
    memory_high: Option<i32>,
    memory_max: Option<i32>,
    firejail_profile: Option<&'a str>,
    implicit_extra_args: Option<&'a [&'a str]>,
    argv_remainder: Vec<String>,
}

fn cgrouped_firejail_command(options: CgroupedFirejailedCommandOptions) -> Command {
    let mut command = Command::new(SYSTEMD_RUN);
    command.args(&["--user", "--scope"]);
    command.args(&["-p", "MemorySwapMax=0"]);

    if let Some(memory_high) = options.memory_high {
        let memory_high_owned_string = format!("MemoryHigh={}M", memory_high);
        command.args(&["-p", memory_high_owned_string.as_str()]);
    }
    if let Some(memory_max) = options.memory_max {
        let memory_max_owned_string = format!("MemoryMax={}M", memory_max);
        command.args(&["-p", memory_max_owned_string.as_str()]);
    }

    if let Some(firejail_profile) = options.firejail_profile {
        command.arg(FIREJAIL);
        command.arg("--ignore=seccomp");
        command.arg(format!("--profile={}", firejail_profile));
    }

    command.arg(options.bin_path);

    if let Some(implicit_extra_args) = options.implicit_extra_args {
        command.args(implicit_extra_args);
    }

    command.args(options.argv_remainder);

    command
}

fn simple_firejail_command(target: &str, args: Vec<String>) -> Command {
    let mut command = Command::new(FIREJAIL);

    command.arg(format!("--profile=/etc/firejail/{}.profile", target));
    command.arg(format!("/usr/bin/{}", target));
    command.args(args);

    command
}

fn quodlibet_command(args: Vec<String>) -> Command {
    let mut file = std::fs::OpenOptions::new()
        .append(true)
        .open(QUODLIBET_FIFO)
        .unwrap();
    file.write_all(match args[0].as_str() {
        "pp" => "play-pause".as_bytes(),
        "sa" => "stop-after 1".as_bytes(),
        _ => panic!(
            "bad argument for quodlibet command: ``{}''",
            args[0].as_str()
        ),
    })
    .unwrap();

    Command::new("/bin/true")
}

fn init_command() -> Command {
    let mut args_less_the_first = std::env::args();
    // Pops the name of this executable.
    args_less_the_first.next();

    // Pops the name of the unner target.
    let target = args_less_the_first.next().unwrap();

    // Copies and collects the remaining argv.
    let args: Vec<String> = args_less_the_first.collect();

    match target.as_str() {
        "ff" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: FIREFOX,
                memory_high: Some(FIREFOX_MEMORY_HIGH),
                memory_max: Some(FIREFOX_MEMORY_MAX),
                firejail_profile: Some(FIREFOX_PROFILE),
                implicit_extra_args: Some(&["-P", FIREFOX_MOZILLA_SFW_PROFILE]),
                argv_remainder: args,
            });
        }
        "keira" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: KEIRA,
                memory_high: Some(FIREFOX_MEMORY_HIGH),
                memory_max: Some(FIREFOX_MEMORY_MAX),
                firejail_profile: Some(KEIRA_PROFILE),
                implicit_extra_args: Some(&["-P", "nightly"]),
                argv_remainder: args,
            });
        }
        "npv" => return simple_firejail_command("mpv", args),
        "q" => return quodlibet_command(args),
        "read" => {
            let formatted_args: Vec<String> = vec![format!("about:reader?url={}", args[0])];
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: FIREFOX,
                memory_high: Some(FIREFOX_MEMORY_HIGH),
                memory_max: Some(FIREFOX_MEMORY_MAX),
                firejail_profile: Some(FIREFOX_PROFILE),
                implicit_extra_args: Some(&["-P", FIREFOX_MOZILLA_SFW_PROFILE]),
                argv_remainder: formatted_args,
            });
        }
        "t" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: TERM,
                memory_high: None,
                memory_max: None,
                firejail_profile: Some(TERM_PROFILE),
                implicit_extra_args: None,
                argv_remainder: args,
            })
        }
        "tbb" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: THUNDERBIRD,
                memory_high: None,
                memory_max: None,
                firejail_profile: Some(THUNDERBIRD_PROFILE),
                implicit_extra_args: None,
                argv_remainder: args,
            });
        }
        "vlk" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: "/usr/bin/vlc",
                memory_high: None,
                memory_max: None,
                firejail_profile: Some("/etc/firejail/vlc.profile"),
                implicit_extra_args: None,
                argv_remainder: args,
            })
        }
        "e" => return simple_firejail_command("evince", args),
        _ => panic!("no handler for ``{}''", target),
    }
}

fn main() {
    let mut command = init_command();
    println!("{:#?}", command);
    command.exec();
}
<commit_msg>unner: Address Pipewire underflows<commit_after>use std::io::Write;
use std::os::unix::process::CommandExt;
use std::process::Command;

const SYSTEMD_RUN: &'static str = "/usr/bin/systemd-run";
const FIREJAIL: &'static str = "/usr/bin/firejail";

const FIREFOX: &'static str = "/usr/bin/firefox";
const FIREFOX_PROFILE: &'static str = "/etc/firejail/firefox.profile";
const FIREFOX_MOZILLA_SFW_PROFILE: &'static str = "default-1473025815439";

const FIREFOX_MEMORY_HIGH: i32 = 4420;
const FIREFOX_MEMORY_MAX: i32 = 5200;

const KEIRA: &'static str = "/home/kalvin/Downloads/.firefox-nightly/firefox";
const KEIRA_PROFILE: &'static str = "/etc/firejail/firefox-nightly.profile";

const MPV: &'static str = "/usr/bin/mpv";
const MPV_PROFILE: &'static str = "/etc/firejail/mpv.profile";

const TERM: &'static str = "/usr/bin/alacritty";
const TERM_PROFILE: &'static str = "/etc/firejail/x-terminal-emulator.profile";

const THUNDERBIRD: &'static str = "/home/kalvin/Downloads/.thunderbird-beta/thunderbird";
const THUNDERBIRD_PROFILE: &'static str = "/etc/firejail/thunderbird-beta.profile";

const QUODLIBET_FIFO: &'static str = "/home/kalvin/.config/quodlibet/control";

#[derive(Debug)]
struct CgroupedFirejailedCommandOptions<'a> {
    bin_path: &'a str,
    memory_high: Option<i32>,
    memory_max: Option<i32>,
    firejail_profile: Option<&'a str>,
    implicit_extra_args: Option<&'a [&'a str]>,
    argv_remainder: Vec<String>,
}

fn cgrouped_firejail_command(options: CgroupedFirejailedCommandOptions) -> Command {
    let mut command = Command::new(SYSTEMD_RUN);
    command.args(&["--user", "--scope"]);
    command.args(&["-p", "MemorySwapMax=0"]);

    if let Some(memory_high) = options.memory_high {
        let memory_high_owned_string = format!("MemoryHigh={}M", memory_high);
        command.args(&["-p", memory_high_owned_string.as_str()]);
    }
    if let Some(memory_max) = options.memory_max {
        let memory_max_owned_string = format!("MemoryMax={}M", memory_max);
        command.args(&["-p", memory_max_owned_string.as_str()]);
    }

    if let Some(firejail_profile) = options.firejail_profile {
        command.arg(FIREJAIL);
        command.arg("--ignore=seccomp");
        command.arg(format!("--profile={}", firejail_profile));
    }

    command.arg(options.bin_path);

    if let Some(implicit_extra_args) = options.implicit_extra_args {
        command.args(implicit_extra_args);
    }

    command.args(options.argv_remainder);

    command
}

fn simple_firejail_command(target: &str, args: Vec<String>) -> Command {
    let mut command = Command::new(FIREJAIL);

    command.arg(format!("--profile=/etc/firejail/{}.profile", target));
    command.arg(format!("/usr/bin/{}", target));
    command.args(args);

    command
}

fn quodlibet_command(args: Vec<String>) -> Command {
    let mut file = std::fs::OpenOptions::new()
        .append(true)
        .open(QUODLIBET_FIFO)
        .unwrap();
    file.write_all(match args[0].as_str() {
        "pp" => "play-pause".as_bytes(),
        "sa" => "stop-after 1".as_bytes(),
        _ => panic!(
            "bad argument for quodlibet command: ``{}''",
            args[0].as_str()
        ),
    })
    .unwrap();

    Command::new("/bin/true")
}

fn init_command() -> Command {
    let mut args_less_the_first = std::env::args();
    // Pops the name of this executable.
    args_less_the_first.next();

    // Pops the name of the unner target.
    let target = args_less_the_first.next().unwrap();

    // Copies and collects the remaining argv.
    let args: Vec<String> = args_less_the_first.collect();

    match target.as_str() {
        "ff" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: FIREFOX,
                memory_high: Some(FIREFOX_MEMORY_HIGH),
                memory_max: Some(FIREFOX_MEMORY_MAX),
                firejail_profile: Some(FIREFOX_PROFILE),
                implicit_extra_args: Some(&["-P", FIREFOX_MOZILLA_SFW_PROFILE]),
                argv_remainder: args,
            });
        }
        "keira" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: KEIRA,
                memory_high: Some(FIREFOX_MEMORY_HIGH),
                memory_max: Some(FIREFOX_MEMORY_MAX),
                firejail_profile: Some(KEIRA_PROFILE),
                implicit_extra_args: Some(&["-P", "nightly"]),
                argv_remainder: args,
            });
        }
        "npv" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: MPV,
                memory_high: None,
                memory_max: None,
                firejail_profile: Some(MPV_PROFILE),
                implicit_extra_args: Some(&["--pulse-buffer=13"]),
                argv_remainder: args,
            });
        }
        "q" => return quodlibet_command(args),
        "read" => {
            let formatted_args: Vec<String> = vec![format!("about:reader?url={}", args[0])];
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: FIREFOX,
                memory_high: Some(FIREFOX_MEMORY_HIGH),
                memory_max: Some(FIREFOX_MEMORY_MAX),
                firejail_profile: Some(FIREFOX_PROFILE),
                implicit_extra_args: Some(&["-P", FIREFOX_MOZILLA_SFW_PROFILE]),
                argv_remainder: formatted_args,
            });
        }
        "t" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: TERM,
                memory_high: None,
                memory_max: None,
                firejail_profile: Some(TERM_PROFILE),
                implicit_extra_args: None,
                argv_remainder: args,
            })
        }
        "tbb" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: THUNDERBIRD,
                memory_high: None,
                memory_max: None,
                firejail_profile: Some(THUNDERBIRD_PROFILE),
                implicit_extra_args: None,
                argv_remainder: args,
            });
        }
        "vlk" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: "/usr/bin/vlc",
                memory_high: None,
                memory_max: None,
                firejail_profile: Some("/etc/firejail/vlc.profile"),
                implicit_extra_args: None,
                argv_remainder: args,
            })
        }
        "e" => return simple_firejail_command("evince", args),
        _ => panic!("no handler for ``{}''", target),
    }
}

fn main() {
    let mut command = init_command();
    println!("{:#?}", command);
    command.exec();
}
<|endoftext|>


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

use special::Error;
use std::f64::consts::PI;

use sys::System;
use types::{Matrix3, Vector3D, Zero};
use consts::ELCC;
use energy::{PairRestriction, RestrictionInfo};

use super::{GlobalPotential, CoulombicPotential, GlobalCache};

/// Wolf summation for coulombic interactions.
///
/// This is a fast, direct, pairwise summation for coulombic potential
/// [Wolf1999].
///
/// # Examples
///
/// ```
/// use lumol::energy::Wolf;
/// use lumol::units;
///
/// // A relatively large cutoff is needed for Wolf summation
/// let wolf = Wolf::new(12.0);
///
/// use lumol::sys::System;
/// use lumol::sys::Particle;
/// use lumol::sys::UnitCell;
/// use lumol::types::Vector3D;
///
/// // Setup a system containing a NaCl pair
/// let mut system = System::new();
/// system.set_cell(UnitCell::cubic(10.0));
///
/// let mut na = Particle::new("Na");
/// na.charge = 1.0;
/// na.position = Vector3D::new(0.0, 0.0, 0.0);
///
/// let mut cl = Particle::new("Cl");
/// cl.charge = -1.0;
/// cl.position = Vector3D::new(2.0, 0.0, 0.0);
///
/// system.add_particle(na);
/// system.add_particle(cl);
///
/// // Use Wolf summation for electrostatic interactions
/// system.interactions_mut().set_coulomb(Box::new(wolf));
///
/// assert_eq!(system.potential_energy(), -0.07292902695393541);
/// ```
///
/// [Wolf1999]: Wolf, D. et al. J. Chem. Phys. 110, 8254 (1999).
#[derive(Clone)]
pub struct Wolf {
    /// Splitting parameter
    alpha: f64,
    /// Cutoff radius in real space
    cutoff: f64,
    /// Energy constant for wolf computation
    energy_cst: f64,
    /// Force constant for wolf computation
    force_cst: f64,
    /// Restriction scheme
    restriction: PairRestriction,
}

impl Wolf {
    /// Create a new Wolf summation, using a real-space cutoff of `cutoff`.
    pub fn new(cutoff: f64) -> Wolf {
        assert!(cutoff > 0.0, "Got a negative cutoff in Wolf summation");
        let alpha = PI/cutoff;
        let e_cst = f64::erfc(alpha*cutoff)/cutoff;
        let f_cst = f64::erfc(alpha*cutoff)/(cutoff*cutoff) + 2.0*alpha/f64::sqrt(PI) * f64::exp(-alpha*alpha*cutoff*cutoff)/cutoff;
        Wolf{
            alpha: alpha,
            cutoff: cutoff,
            energy_cst: e_cst,
            force_cst: f_cst,
            restriction: PairRestriction::None,
        }
    }

    /// Compute the energy for the pair of particles with charge `qi` and `qj`,
    /// at the distance of `rij`. The `scaling` parameter comes from the
    /// restriction associated with this potential.
    #[inline]
    fn energy_pair(&self, info: RestrictionInfo, qi: f64, qj: f64, rij: f64) -> f64 {
        if rij > self.cutoff || info.excluded {
            return 0.0;
        }
        info.scaling * qi * qj * (f64::erfc(self.alpha*rij)/rij - self.energy_cst) / ELCC
    }

    /// Compute the energy for self interaction of a particle with charge `qi`
    #[inline]
    fn energy_self(&self, qi: f64) -> f64 {
        qi * qi * (self.energy_cst/2.0 + self.alpha/f64::sqrt(PI)) / ELCC
    }

    /// Compute the force for self the pair of particles with charge `qi` and
    /// `qj`, at the distance of `rij`. The `scaling` parameter comes from the
    /// restriction associated with this potential.
    #[inline]
    fn force_pair(&self, info: RestrictionInfo, qi: f64, qj: f64, rij: Vector3D) -> Vector3D {
        let d = rij.norm();
        if d > self.cutoff || info.excluded {
            return Vector3D::zero();
        }
        let factor = f64::erfc(self.alpha*d)/(d*d) + 2.0*self.alpha/f64::sqrt(PI) * f64::exp(-self.alpha*self.alpha*d*d)/d;
        return info.scaling * qi * qj * (factor - self.force_cst) * rij.normalized() / ELCC;
    }
}

impl GlobalCache for Wolf {
    fn move_particles_cost(&self, system: &System, idxes: &[usize], newpos: &[Vector3D]) -> f64 {
        let mut e_old = 0.0;
        let mut e_new = 0.0;

        // Iterate over all interactions between a moved particle and a
        // particle not moved
        for (idx, &i) in idxes.iter().enumerate() {
            let qi = system[i].charge;
            if qi == 0.0 {continue;}
            for j in (0..system.size()).filter(|x| !idxes.contains(x)) {
                let qj = system[j].charge;
                if qj == 0.0 {continue;}

                let r_old = system.cell().distance(&system[i].position, &system[j].position);
                let r_new = system.cell().distance(&newpos[idx], &system[j].position);

                let distance = system.bond_distance(i, j);
                let info = self.restriction.information(distance);

                e_old += self.energy_pair(info, qi, qj, r_old);
                e_new += self.energy_pair(info, qi, qj, r_new);
            }
        }

        // Iterate over all interactions between two moved particles
        for (idx, &i) in idxes.iter().enumerate() {
            let qi = system[i].charge;
            if qi == 0.0 {continue;}
            for (jdx, &j) in idxes.iter().enumerate().skip(idx + 1) {
                let qj = system[j].charge;
                if qj == 0.0 {continue;}

                let r_old = system.distance(i, j);
                let r_new = system.cell().distance(&newpos[idx], &newpos[jdx]);

                let distance = system.bond_distance(i, j);
                let info = self.restriction.information(distance);

                e_old += self.energy_pair(info, qi, qj, r_old);
                e_new += self.energy_pair(info, qi, qj, r_new);
            }
        }

        return e_new - e_old;
    }

    fn update(&self) {
        // Nothing to do
    }
}

impl GlobalPotential for Wolf {
    fn cutoff(&self) -> Option<f64> {
        Some(self.cutoff)
    }

    fn energy(&self, system: &System) -> f64 {
        let natoms = system.size();
        let mut res = 0.0;
        for i in 0..natoms {
            let qi = system[i].charge;
            if qi == 0.0 {continue}
            for j in i+1..natoms {
                let qj = system[j].charge;
                if qj == 0.0 {continue}

                let distance = system.bond_distance(i, j);
                let info = self.restriction.information(distance);

                let rij = system.distance(i, j);
                res += self.energy_pair(info, qi, qj, rij);
            }
            // Remove self term
            res -= self.energy_self(qi);
        }
        return res;
    }

    fn forces(&self, system: &System) -> Vec<Vector3D> {
        let natoms = system.size();
        let mut res = vec![Vector3D::zero(); natoms];
        for i in 0..natoms {
            let qi = system[i].charge;
            if qi == 0.0 {continue}
            for j in i+1..natoms {
                let qj = system[j].charge;
                if qj == 0.0 {continue}

                let distance = system.bond_distance(i, j);
                let info = self.restriction.information(distance);

                let rij = system.nearest_image(i, j);
                let force = self.force_pair(info, qi, qj, rij);
                res[i] += force;
                res[j] -= force;
            }
        }
        return res;
    }

    fn virial(&self, system: &System) -> Matrix3 {
        let natoms = system.size();
        let mut res = Matrix3::zero();
        for i in 0..natoms {
            let qi = system[i].charge;
            if qi == 0.0 {continue}
            for j in i+1..natoms {
                let qj = system[j].charge;
                if qj == 0.0 {continue}

                let distance = system.bond_distance(i, j);
                let info = self.restriction.information(distance);

                let rij = system.nearest_image(i, j);
                let force = self.force_pair(info, qi, qj, rij);
                res += force.tensorial(&rij);
            }
        }
        return res;
    }
}

impl CoulombicPotential for Wolf {
    fn set_restriction(&mut self, restriction: PairRestriction) {
        self.restriction = restriction;
    }
}

#[cfg(test)]
mod tests {
    pub use super::*;
    use sys::{System, UnitCell, Particle};
    use types::{Vector3D, Zero};
    use energy::GlobalPotential;

    const E_BRUTE_FORCE: f64 = -0.09262397663346732;

    pub fn testing_system() -> System {
        let mut system = System::from_cell(UnitCell::cubic(20.0));

        system.add_particle(Particle::new("Cl"));
        system[0].charge = -1.0;
        system[0].position = Vector3D::zero();

        system.add_particle(Particle::new("Na"));
        system[1].charge = 1.0;
        system[1].position = Vector3D::new(1.5, 0.0, 0.0);

        return system;
    }

    #[test]
    fn energy() {
        let system = testing_system();
        let wolf = Wolf::new(8.0);

        let e = wolf.energy(&system);
        // Wolf is not very good for heterogeneous systems
        assert_ulps_eq!(e, E_BRUTE_FORCE, epsilon=1e-2);
    }

    #[test]
    fn forces() {
        let mut system = testing_system();
        let wolf = Wolf::new(8.0);

        let forces = wolf.forces(&system);
        let norm = (forces[0] + forces[1]).norm();
        // Total force should be null
        assert_ulps_eq!(norm, 0.0);

        // Finite difference computation of the force
        let e = wolf.energy(&system);
        let eps = 1e-9;
        system[0].position[0] += eps;

        let e1 = wolf.energy(&system);
        let force = wolf.forces(&system)[0][0];
        assert_relative_eq!((e - e1) / eps, force, epsilon=1e-6);
    }
}
<commit_msg>Add tests for Wolf MC cache<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 Lumol's contributors — BSD license

use special::Error;
use std::f64::consts::PI;

use sys::System;
use types::{Matrix3, Vector3D, Zero};
use consts::ELCC;
use energy::{PairRestriction, RestrictionInfo};

use super::{GlobalPotential, CoulombicPotential, GlobalCache};

/// Wolf summation for coulombic interactions.
///
/// This is a fast, direct, pairwise summation for coulombic potential
/// [Wolf1999].
///
/// # Examples
///
/// ```
/// use lumol::energy::Wolf;
/// use lumol::units;
///
/// // A relatively large cutoff is needed for Wolf summation
/// let wolf = Wolf::new(12.0);
///
/// use lumol::sys::System;
/// use lumol::sys::Particle;
/// use lumol::sys::UnitCell;
/// use lumol::types::Vector3D;
///
/// // Setup a system containing a NaCl pair
/// let mut system = System::new();
/// system.set_cell(UnitCell::cubic(10.0));
///
/// let mut na = Particle::new("Na");
/// na.charge = 1.0;
/// na.position = Vector3D::new(0.0, 0.0, 0.0);
///
/// let mut cl = Particle::new("Cl");
/// cl.charge = -1.0;
/// cl.position = Vector3D::new(2.0, 0.0, 0.0);
///
/// system.add_particle(na);
/// system.add_particle(cl);
///
/// // Use Wolf summation for electrostatic interactions
/// system.interactions_mut().set_coulomb(Box::new(wolf));
///
/// assert_eq!(system.potential_energy(), -0.07292902695393541);
/// ```
///
/// [Wolf1999]: Wolf, D. et al. J. Chem. Phys. 110, 8254 (1999).
#[derive(Clone)]
pub struct Wolf {
    /// Splitting parameter
    alpha: f64,
    /// Cutoff radius in real space
    cutoff: f64,
    /// Energy constant for wolf computation
    energy_cst: f64,
    /// Force constant for wolf computation
    force_cst: f64,
    /// Restriction scheme
    restriction: PairRestriction,
}

impl Wolf {
    /// Create a new Wolf summation, using a real-space cutoff of `cutoff`.
    pub fn new(cutoff: f64) -> Wolf {
        assert!(cutoff > 0.0, "Got a negative cutoff in Wolf summation");
        let alpha = PI/cutoff;
        let e_cst = f64::erfc(alpha*cutoff)/cutoff;
        let f_cst = f64::erfc(alpha*cutoff)/(cutoff*cutoff) + 2.0*alpha/f64::sqrt(PI) * f64::exp(-alpha*alpha*cutoff*cutoff)/cutoff;
        Wolf{
            alpha: alpha,
            cutoff: cutoff,
            energy_cst: e_cst,
            force_cst: f_cst,
            restriction: PairRestriction::None,
        }
    }

    /// Compute the energy for the pair of particles with charge `qi` and `qj`,
    /// at the distance of `rij`. The `scaling` parameter comes from the
    /// restriction associated with this potential.
    #[inline]
    fn energy_pair(&self, info: RestrictionInfo, qi: f64, qj: f64, rij: f64) -> f64 {
        if rij > self.cutoff || info.excluded {
            return 0.0;
        }
        info.scaling * qi * qj * (f64::erfc(self.alpha*rij)/rij - self.energy_cst) / ELCC
    }

    /// Compute the energy for self interaction of a particle with charge `qi`
    #[inline]
    fn energy_self(&self, qi: f64) -> f64 {
        qi * qi * (self.energy_cst/2.0 + self.alpha/f64::sqrt(PI)) / ELCC
    }

    /// Compute the force for self the pair of particles with charge `qi` and
    /// `qj`, at the distance of `rij`. The `scaling` parameter comes from the
    /// restriction associated with this potential.
    #[inline]
    fn force_pair(&self, info: RestrictionInfo, qi: f64, qj: f64, rij: Vector3D) -> Vector3D {
        let d = rij.norm();
        if d > self.cutoff || info.excluded {
            return Vector3D::zero();
        }
        let factor = f64::erfc(self.alpha*d)/(d*d) + 2.0*self.alpha/f64::sqrt(PI) * f64::exp(-self.alpha*self.alpha*d*d)/d;
        return info.scaling * qi * qj * (factor - self.force_cst) * rij.normalized() / ELCC;
    }
}

impl GlobalCache for Wolf {
    fn move_particles_cost(&self, system: &System, idxes: &[usize], newpos: &[Vector3D]) -> f64 {
        let mut e_old = 0.0;
        let mut e_new = 0.0;

        // Iterate over all interactions between a moved particle and a
        // particle not moved
        for (idx, &i) in idxes.iter().enumerate() {
            let qi = system[i].charge;
            if qi == 0.0 {continue;}
            for j in (0..system.size()).filter(|x| !idxes.contains(x)) {
                let qj = system[j].charge;
                if qj == 0.0 {continue;}

                let r_old = system.cell().distance(&system[i].position, &system[j].position);
                let r_new = system.cell().distance(&newpos[idx], &system[j].position);

                let distance = system.bond_distance(i, j);
                let info = self.restriction.information(distance);

                e_old += self.energy_pair(info, qi, qj, r_old);
                e_new += self.energy_pair(info, qi, qj, r_new);
            }
        }

        // Iterate over all interactions between two moved particles
        for (idx, &i) in idxes.iter().enumerate() {
            let qi = system[i].charge;
            if qi == 0.0 {continue;}
            for (jdx, &j) in idxes.iter().enumerate().skip(idx + 1) {
                let qj = system[j].charge;
                if qj == 0.0 {continue;}

                let r_old = system.distance(i, j);
                let r_new = system.cell().distance(&newpos[idx], &newpos[jdx]);

                let distance = system.bond_distance(i, j);
                let info = self.restriction.information(distance);

                e_old += self.energy_pair(info, qi, qj, r_old);
                e_new += self.energy_pair(info, qi, qj, r_new);
            }
        }

        return e_new - e_old;
    }

    fn update(&self) {
        // Nothing to do
    }
}

impl GlobalPotential for Wolf {
    fn cutoff(&self) -> Option<f64> {
        Some(self.cutoff)
    }

    fn energy(&self, system: &System) -> f64 {
        let natoms = system.size();
        let mut res = 0.0;
        for i in 0..natoms {
            let qi = system[i].charge;
            if qi == 0.0 {continue}
            for j in i+1..natoms {
                let qj = system[j].charge;
                if qj == 0.0 {continue}

                let distance = system.bond_distance(i, j);
                let info = self.restriction.information(distance);

                let rij = system.distance(i, j);
                res += self.energy_pair(info, qi, qj, rij);
            }
            // Remove self term
            res -= self.energy_self(qi);
        }
        return res;
    }

    fn forces(&self, system: &System) -> Vec<Vector3D> {
        let natoms = system.size();
        let mut res = vec![Vector3D::zero(); natoms];
        for i in 0..natoms {
            let qi = system[i].charge;
            if qi == 0.0 {continue}
            for j in i+1..natoms {
                let qj = system[j].charge;
                if qj == 0.0 {continue}

                let distance = system.bond_distance(i, j);
                let info = self.restriction.information(distance);

                let rij = system.nearest_image(i, j);
                let force = self.force_pair(info, qi, qj, rij);
                res[i] += force;
                res[j] -= force;
            }
        }
        return res;
    }

    fn virial(&self, system: &System) -> Matrix3 {
        let natoms = system.size();
        let mut res = Matrix3::zero();
        for i in 0..natoms {
            let qi = system[i].charge;
            if qi == 0.0 {continue}
            for j in i+1..natoms {
                let qj = system[j].charge;
                if qj == 0.0 {continue}

                let distance = system.bond_distance(i, j);
                let info = self.restriction.information(distance);

                let rij = system.nearest_image(i, j);
                let force = self.force_pair(info, qi, qj, rij);
                res += force.tensorial(&rij);
            }
        }
        return res;
    }
}

impl CoulombicPotential for Wolf {
    fn set_restriction(&mut self, restriction: PairRestriction) {
        self.restriction = restriction;
    }
}

#[cfg(test)]
mod tests {
    pub use super::*;
    use sys::{System, UnitCell, Particle};
    use types::{Vector3D, Zero};
    use energy::GlobalPotential;

    const E_BRUTE_FORCE: f64 = -0.09262397663346732;

    pub fn testing_system() -> System {
        let mut system = System::from_cell(UnitCell::cubic(20.0));

        system.add_particle(Particle::new("Cl"));
        system[0].charge = -1.0;
        system[0].position = Vector3D::zero();

        system.add_particle(Particle::new("Na"));
        system[1].charge = 1.0;
        system[1].position = Vector3D::new(1.5, 0.0, 0.0);

        return system;
    }

    #[test]
    fn energy() {
        let system = testing_system();
        let wolf = Wolf::new(8.0);

        let e = wolf.energy(&system);
        // Wolf is not very good for heterogeneous systems
        assert_ulps_eq!(e, E_BRUTE_FORCE, epsilon=1e-2);
    }

    #[test]
    fn forces() {
        let mut system = testing_system();
        let wolf = Wolf::new(8.0);

        let forces = wolf.forces(&system);
        let norm = (forces[0] + forces[1]).norm();
        // Total force should be null
        assert_ulps_eq!(norm, 0.0);

        // Finite difference computation of the force
        let e = wolf.energy(&system);
        let eps = 1e-9;
        system[0].position[0] += eps;

        let e1 = wolf.energy(&system);
        let force = wolf.forces(&system)[0][0];
        assert_relative_eq!((e - e1) / eps, force, epsilon=1e-6);
    }

    mod cache {
        use super::*;
        use sys::System;
        use types::Vector3D;
        use energy::{GlobalPotential, PairRestriction, CoulombicPotential, GlobalCache};

        pub fn testing_system() -> System {
            use utils::system_from_xyz;
            let mut system = system_from_xyz("6
            bonds
            O  0.0  0.0  0.0
            H -0.7 -0.7  0.3
            H  0.3 -0.3 -0.8
            O  2.0  2.0  0.0
            H  1.3  1.3  0.3
            H  2.3  1.7 -0.8
            ");
            system.set_cell(UnitCell::cubic(20.0));
            assert!(system.molecules().len() == 2);

            for particle in &mut system {
                if particle.name() == "O" {
                    particle.charge = -0.8476;
                } else if particle.name() == "H" {
                    particle.charge = 0.4238;
                }
            }
            return system;
        }

        #[test]
        fn move_atoms() {
            let mut system = testing_system();
            let mut wolf = Wolf::new(8.0);
            wolf.set_restriction(PairRestriction::InterMolecular);

            let check = wolf.clone();

            let old_e = check.energy(&system);
            let idxes = &[0, 1];
            let newpos = &[Vector3D::new(0.0, 0.0, 0.5), Vector3D::new(-0.7, 0.2, 1.5)];

            let cost = wolf.move_particles_cost(&system, idxes, newpos);

            system[0].position = newpos[0];
            system[1].position = newpos[1];
            let new_e = check.energy(&system);
            assert_ulps_eq!(cost, new_e - old_e);
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::collections::hashmap;
use std::default::Default;
use std::slice;
use stream::wire_format;
use clear::Clear;

#[deriving(Show)]
pub enum UnknownValue {
    UnknownFixed32(u32),
    UnknownFixed64(u64),
    UnknownVarint(u64),
    UnknownLengthDelimited(Vec<u8>),
}

impl UnknownValue {
    pub fn wire_type(&self) -> wire_format::WireType {
        self.get_ref().wire_type()
    }

    pub fn get_ref<'s>(&'s self) -> UnknownValueRef<'s> {
        match *self {
            UnknownFixed32(fixed32) => UnknownFixed32Ref(fixed32),
            UnknownFixed64(fixed64) => UnknownFixed64Ref(fixed64),
            UnknownVarint(varint) => UnknownVarintRef(varint),
            UnknownLengthDelimited(ref bytes) => UnknownLengthDelimitedRef(bytes.as_slice()),
        }
    }
}

pub enum UnknownValueRef<'o> {
    UnknownFixed32Ref(u32),
    UnknownFixed64Ref(u64),
    UnknownVarintRef(u64),
    UnknownLengthDelimitedRef(&'o [u8]),
}

impl<'o> UnknownValueRef<'o> {
    pub fn wire_type(&self) -> wire_format::WireType {
        match *self {
            UnknownFixed32Ref(_) => wire_format::WireTypeFixed32,
            UnknownFixed64Ref(_) => wire_format::WireTypeFixed64,
            UnknownVarintRef(_) => wire_format::WireTypeVarint,
            UnknownLengthDelimitedRef(_) => wire_format::WireTypeLengthDelimited,
        }
    }
}

#[deriving(Clone,PartialEq,Eq,Show,Default)]
pub struct UnknownValues {
    pub fixed32: Vec<u32>,
    pub fixed64: Vec<u64>,
    pub varint: Vec<u64>,
    pub length_delimited: Vec<Vec<u8>>,
}

impl UnknownValues {
    pub fn add_value(&mut self, value: UnknownValue) {
        match value {
            UnknownFixed64(fixed64) => self.fixed64.push(fixed64),
            UnknownFixed32(fixed32) => self.fixed32.push(fixed32),
            UnknownVarint(varint) => self.varint.push(varint),
            UnknownLengthDelimited(length_delimited) => self.length_delimited.push(length_delimited),
        };
    }

    pub fn iter<'s>(&'s self) -> UnknownValuesIter<'s> {
        UnknownValuesIter {
            fixed32: self.fixed32.iter(),
            fixed64: self.fixed64.iter(),
            varint: self.varint.iter(),
            length_delimited: self.length_delimited.iter(),
        }
    }
}

pub struct UnknownValuesIter<'o> {
    fixed32: slice::Items<'o, u32>,
    fixed64: slice::Items<'o, u64>,
    varint: slice::Items<'o, u64>,
    length_delimited: slice::Items<'o, Vec<u8>>,
}

impl<'o> Iterator<UnknownValueRef<'o>> for UnknownValuesIter<'o> {
    fn next(&mut self) -> Option<UnknownValueRef<'o>> {
        let fixed32 = self.fixed32.next();
        if fixed32.is_some() {
            return Some(UnknownFixed32Ref(*fixed32.unwrap()));
        }
        let fixed64 = self.fixed64.next();
        if fixed64.is_some() {
            return Some(UnknownFixed64Ref(*fixed64.unwrap()));
        }
        let varint = self.varint.next();
        if varint.is_some() {
            return Some(UnknownVarintRef(*varint.unwrap()));
        }
        let length_delimited = self.length_delimited.next();
        if length_delimited.is_some() {
            return Some(UnknownLengthDelimitedRef(length_delimited.as_ref().unwrap().as_slice()))
        }
        None
    }
}

#[deriving(Clone,PartialEq,Eq,Show,Default)]
pub struct UnknownFields {
    // option is needed, because HashMap constructor performs allocation,
    // and very expensive
    pub fields: Option<Box<HashMap<u32, UnknownValues>>>,
}

impl UnknownFields {
    pub fn new() -> UnknownFields {
        Default::default()
    }

    fn init_map(&mut self) {
        if self.fields.is_none() {
            self.fields = Some(box Default::default());
        }
    }

    fn find_field<'a>(&'a mut self, number: u32) -> &'a mut UnknownValues {
        self.init_map();

        self.fields.as_mut().unwrap()
            .find_or_insert_with(number, |_| Default::default())
    }

    pub fn add_fixed32(&mut self, number: u32, fixed32: u32) {
        self.find_field(number).fixed32.push(fixed32);
    }

    pub fn add_fixed64(&mut self, number: u32, fixed64: u64) {
        self.find_field(number).fixed64.push(fixed64);
    }

    pub fn add_varint(&mut self, number: u32, varint: u64) {
        self.find_field(number).varint.push(varint);
    }

    pub fn add_length_delimited(&mut self, number: u32, length_delimited: Vec<u8>) {
        self.find_field(number).length_delimited.push(length_delimited);
    }

    pub fn add_value(&mut self, number: u32, value: UnknownValue) {
        self.find_field(number).add_value(value);
    }

    pub fn iter<'s>(&'s self) -> UnknownFieldIter<'s> {
        UnknownFieldIter {
            entries: self.fields.as_ref().map(|m| m.iter())
        }
    }
}

impl Clear for UnknownFields {
    fn clear(&mut self) {
        if self.fields.is_some() {
            self.fields.as_mut().unwrap().clear();
        }
    }
}

pub struct UnknownFieldIter<'s> {
    entries: Option<hashmap::Entries<'s, u32, UnknownValues>>,
}

impl<'s> Iterator<(u32, &'s UnknownValues)> for UnknownFieldIter<'s> {
    fn next(&mut self) -> Option<(u32, &'s UnknownValues)> {
        if self.entries.is_none() {
            None
        } else {
            self.entries.as_mut().unwrap().next().map(|(&number, values)| (number, values))
        }
    }
}
<commit_msg>Rust no longer has find_or_insert_with op<commit_after>use std::collections::HashMap;
use std::collections::hashmap;
use std::default::Default;
use std::slice;
use stream::wire_format;
use clear::Clear;

#[deriving(Show)]
pub enum UnknownValue {
    UnknownFixed32(u32),
    UnknownFixed64(u64),
    UnknownVarint(u64),
    UnknownLengthDelimited(Vec<u8>),
}

impl UnknownValue {
    pub fn wire_type(&self) -> wire_format::WireType {
        self.get_ref().wire_type()
    }

    pub fn get_ref<'s>(&'s self) -> UnknownValueRef<'s> {
        match *self {
            UnknownFixed32(fixed32) => UnknownFixed32Ref(fixed32),
            UnknownFixed64(fixed64) => UnknownFixed64Ref(fixed64),
            UnknownVarint(varint) => UnknownVarintRef(varint),
            UnknownLengthDelimited(ref bytes) => UnknownLengthDelimitedRef(bytes.as_slice()),
        }
    }
}

pub enum UnknownValueRef<'o> {
    UnknownFixed32Ref(u32),
    UnknownFixed64Ref(u64),
    UnknownVarintRef(u64),
    UnknownLengthDelimitedRef(&'o [u8]),
}

impl<'o> UnknownValueRef<'o> {
    pub fn wire_type(&self) -> wire_format::WireType {
        match *self {
            UnknownFixed32Ref(_) => wire_format::WireTypeFixed32,
            UnknownFixed64Ref(_) => wire_format::WireTypeFixed64,
            UnknownVarintRef(_) => wire_format::WireTypeVarint,
            UnknownLengthDelimitedRef(_) => wire_format::WireTypeLengthDelimited,
        }
    }
}

#[deriving(Clone,PartialEq,Eq,Show,Default)]
pub struct UnknownValues {
    pub fixed32: Vec<u32>,
    pub fixed64: Vec<u64>,
    pub varint: Vec<u64>,
    pub length_delimited: Vec<Vec<u8>>,
}

impl UnknownValues {
    pub fn add_value(&mut self, value: UnknownValue) {
        match value {
            UnknownFixed64(fixed64) => self.fixed64.push(fixed64),
            UnknownFixed32(fixed32) => self.fixed32.push(fixed32),
            UnknownVarint(varint) => self.varint.push(varint),
            UnknownLengthDelimited(length_delimited) => self.length_delimited.push(length_delimited),
        };
    }

    pub fn iter<'s>(&'s self) -> UnknownValuesIter<'s> {
        UnknownValuesIter {
            fixed32: self.fixed32.iter(),
            fixed64: self.fixed64.iter(),
            varint: self.varint.iter(),
            length_delimited: self.length_delimited.iter(),
        }
    }
}

pub struct UnknownValuesIter<'o> {
    fixed32: slice::Items<'o, u32>,
    fixed64: slice::Items<'o, u64>,
    varint: slice::Items<'o, u64>,
    length_delimited: slice::Items<'o, Vec<u8>>,
}

impl<'o> Iterator<UnknownValueRef<'o>> for UnknownValuesIter<'o> {
    fn next(&mut self) -> Option<UnknownValueRef<'o>> {
        let fixed32 = self.fixed32.next();
        if fixed32.is_some() {
            return Some(UnknownFixed32Ref(*fixed32.unwrap()));
        }
        let fixed64 = self.fixed64.next();
        if fixed64.is_some() {
            return Some(UnknownFixed64Ref(*fixed64.unwrap()));
        }
        let varint = self.varint.next();
        if varint.is_some() {
            return Some(UnknownVarintRef(*varint.unwrap()));
        }
        let length_delimited = self.length_delimited.next();
        if length_delimited.is_some() {
            return Some(UnknownLengthDelimitedRef(length_delimited.as_ref().unwrap().as_slice()))
        }
        None
    }
}

#[deriving(Clone,PartialEq,Eq,Show,Default)]
pub struct UnknownFields {
    // option is needed, because HashMap constructor performs allocation,
    // and very expensive
    pub fields: Option<Box<HashMap<u32, UnknownValues>>>,
}

impl UnknownFields {
    pub fn new() -> UnknownFields {
        Default::default()
    }

    fn init_map(&mut self) {
        if self.fields.is_none() {
            self.fields = Some(box Default::default());
        }
    }

    fn find_field<'a>(&'a mut self, number: u32) -> &'a mut UnknownValues {
        self.init_map();

        match self.fields.as_mut().unwrap().entry(number) {
            hashmap::Occupied(e) => e.into_mut(),
            hashmap::Vacant(e) => e.set(Default::default()),
        }
    }

    pub fn add_fixed32(&mut self, number: u32, fixed32: u32) {
        self.find_field(number).fixed32.push(fixed32);
    }

    pub fn add_fixed64(&mut self, number: u32, fixed64: u64) {
        self.find_field(number).fixed64.push(fixed64);
    }

    pub fn add_varint(&mut self, number: u32, varint: u64) {
        self.find_field(number).varint.push(varint);
    }

    pub fn add_length_delimited(&mut self, number: u32, length_delimited: Vec<u8>) {
        self.find_field(number).length_delimited.push(length_delimited);
    }

    pub fn add_value(&mut self, number: u32, value: UnknownValue) {
        self.find_field(number).add_value(value);
    }

    pub fn iter<'s>(&'s self) -> UnknownFieldIter<'s> {
        UnknownFieldIter {
            entries: self.fields.as_ref().map(|m| m.iter())
        }
    }
}

impl Clear for UnknownFields {
    fn clear(&mut self) {
        if self.fields.is_some() {
            self.fields.as_mut().unwrap().clear();
        }
    }
}

pub struct UnknownFieldIter<'s> {
    entries: Option<hashmap::Entries<'s, u32, UnknownValues>>,
}

impl<'s> Iterator<(u32, &'s UnknownValues)> for UnknownFieldIter<'s> {
    fn next(&mut self) -> Option<(u32, &'s UnknownValues)> {
        if self.entries.is_none() {
            None
        } else {
            self.entries.as_mut().unwrap().next().map(|(&number, values)| (number, values))
        }
    }
}
<|endoftext|>


<commit_before>use definitions::bytecode;
use definitions::typedef::*;
use error::*;
use ieee754::Ieee754;
use num::traits::Num;
use num::traits::cast::FromPrimitive;
use output::Mountable;
use std::fs::File;
use std::io::prelude::*;
use std::mem;
use std::ops::{BitOrAssign, ShlAssign};
use std::path::Path;

/// We can adjust the buffer register count here
pub const BUF_REG_COUNT: usize = 32;

/// A register type for comparing two values
struct CompareRegister {
    cra: Word,
    crb: Word,
}

#[derive(Default)]
struct ImageData {
    /// The currently loaded image
    data: Image,
    /// The program counter
    pc: Address,
}

#[derive(Default)]
struct StackData {
    /// The stack pointer
    ptr: Address,
    data: Vec<Word>,
}

/// The whole state of the VM
pub struct VM {
    /// The buffer registers
    buf_regs: [Word; BUF_REG_COUNT],
    cmp_reg: CompareRegister,
    image: ImageData,
    stack: StackData,
}

impl VM {
    pub fn new() -> VM {
        VM {
            image: ImageData::default(),
            stack: StackData::default(),
            buf_regs: [0; BUF_REG_COUNT],
            cmp_reg: CompareRegister { cra: 0, crb: 0 },
        }
    }

    pub fn exec<P: AsRef<Path>>(&mut self, path: P) -> VMResult<()> {
        let mut image_file = File::open(path).chain_err(|| "unable to open game image file")?;
        image_file.read_to_end(&mut self.image.data).chain_err(|| "unable to read game image file")?;

        while self.image.pc < self.image.data.len() {
            let byte = self.current_byte().chain_err(|| "unable to read current byte")?;

            match byte {
                bytecode::HALT => break,
                bytecode::ADD => self.add().chain_err(|| "unable to execute 'add' instruction")?,
                bytecode::SUB => self.sub().chain_err(|| "unable to execute 'sub' instruction")?,
                bytecode::MUL => self.mul().chain_err(|| "unable to execute 'mul' instruction")?,
                bytecode::DIV => self.div().chain_err(|| "unable to execute 'div' instruction")?,
                bytecode::PUSH => {
                    let res = self.read().chain_err(|| "unable to read word")?;

                    self.push_word(res).chain_err(|| "unable to push value to the stack")?;
                }
                bytecode::JMP => {
                    let addr: Word = self.read().chain_err(|| "unable to read word")?;

                    self.jmp(addr as Address);
                    continue;
                }
                bytecode::JZ => {
                    let addr: Word = self.read().chain_err(|| "unable to read word")?;

                    let top_of_stack = self.peek_number()
                        .chain_err(|| "unable to get current top of stack")?;

                    if top_of_stack == 0.0 {
                        self.jmp(addr as Address);
                        continue;
                    }
                }
                bytecode::JNZ => {
                    let addr: Word = self.read().chain_err(|| "unable to read word")?;

                    let top_of_stack = self.peek_number()
                        .chain_err(|| "unable to get current top of stack")?;

                    if top_of_stack != 0.0 {
                        self.jmp(addr as Address);
                        continue;
                    }
                }
                _ => {
                    bail!(
                        "unexpected opcode {:02x} at address {:?}",
                        byte,
                        self.image.pc
                    )
                }
            }

            self.advance_pc();
        }

        Ok(())
    }

    pub fn mount<T: Mountable>(&mut self, device: T) -> VMResult<()> {
        device.run();

        Ok(())
    }

    fn push_word(&mut self, value: Word) -> VMResult<()> {
        if !self.stack.data.is_empty() {
            self.stack.ptr += 1;
        }

        self.stack.data.push(value);

        Ok(())
    }

    fn push_number(&mut self, value: Number) -> VMResult<()> {
        self.push_word(value.bits())
    }

    fn pop_word(&mut self) -> VMResult<Word> {
        if self.stack.data.is_empty() {
            bail!("unable to pop word off an empty Stack");
        }

        let res = self.stack.data.remove(self.stack.ptr);
        if !self.stack.data.is_empty() {
            self.stack.ptr -= 1;
        }

        Ok(res)
    }

    fn pop_number(&mut self) -> VMResult<Number> {
        let top = self.pop_word().chain_err(|| "unable to pop word off the stack")?;
        Ok(Number::from_bits(top))
    }

    fn add(&mut self) -> VMResult<()> {
        let b = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        let a = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        self.push_number(a + b).chain_err(|| "unable to push value to the stack")?;
        Ok(())
    }

    fn sub(&mut self) -> VMResult<()> {
        let b = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        let a = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        self.push_number(a - b).chain_err(|| "unable to push to stack")?;
        Ok(())
    }

    fn mul(&mut self) -> VMResult<()> {
        let b = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        let a = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        self.push_number(a * b).chain_err(|| "unable to push to stack")?;
        Ok(())
    }

    fn div(&mut self) -> VMResult<()> {
        let b = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        let a = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        self.push_number(a / b).chain_err(|| "unable to push to stack")?;
        Ok(())
    }

    fn jmp(&mut self, addr: Address) {
        self.image.pc = addr;
    }

    fn read<T: FromPrimitive + Num + ShlAssign<u8> + BitOrAssign>(&mut self) -> VMResult<T> {
        // Build a Word from single bytes
        let mut res: T = T::zero();

        let length = mem::size_of::<T>();

        for _ in 0..length {
            res <<= 8u8;
            self.advance_pc();
            let current_byte = self.current_byte().chain_err(|| "unable to read current byte")?;
            if let Some(number) = T::from_u8(current_byte) {
                res |= number;
            } else {
                bail!("unable to convert from u8");
            }

        }

        Ok(res)
    }

    fn advance_pc(&mut self) {
        self.image.pc += 1;
    }

    fn current_byte(&mut self) -> VMResult<Byte> {
        if self.image.pc < self.image.data.len() {
            Ok(self.image.data[self.image.pc])
        } else {
            bail!("program counter out of bounds");
        }
    }

    fn peek_word(&mut self) -> VMResult<Word> {
        if self.stack.ptr < self.stack.data.len() {
            Ok(self.stack.data[self.stack.ptr])
        } else {
            bail!("stack pointer out of bounds");
        }
    }

    fn peek_number(&mut self) -> VMResult<Number> {
        let top = self.peek_word().chain_err(|| "unable to peek for word")?;
        Ok(Number::from_bits(top))
    }
}
<commit_msg>Moved image methods into separate struct<commit_after>use definitions::bytecode;
use definitions::typedef::*;
use error::*;
use ieee754::Ieee754;
use num::traits::Num;
use num::traits::cast::FromPrimitive;
use output::Mountable;
use std::fs::File;
use std::io::prelude::*;
use std::mem;
use std::ops::{BitOrAssign, ShlAssign};
use std::path::Path;

/// We can adjust the buffer register count here
pub const BUF_REG_COUNT: usize = 32;

/// A register type for comparing two values
struct CompareRegister {
    cra: Word,
    crb: Word,
}

#[derive(Default)]
struct ImageData {
    /// The currently loaded image
    data: Image,
    /// The program counter
    pc: Address,
}

impl ImageData {
    pub fn from_path<P: AsRef<Path>>(&mut self, path: P) -> VMResult<()> {
        let mut image_file = File::open(path).chain_err(|| "unable to open game image file")?;
        image_file.read_to_end(&mut self.data).chain_err(|| "unable to read game image file")?;

        Ok(())
    }

    fn advance_pc(&mut self) {
        self.pc += 1;
    }

    fn current_byte(&mut self) -> VMResult<Byte> {
        if self.pc < self.data.len() {
            Ok(self.data[self.pc])
        } else {
            bail!("program counter out of bounds");
        }
    }

    fn jmp(&mut self, addr: Address) {
        self.pc = addr;
    }

    fn read<T: FromPrimitive + Num + ShlAssign<u8> + BitOrAssign>(&mut self) -> VMResult<T> {
        // Build a Word from single bytes
        let mut res: T = T::zero();

        let length = mem::size_of::<T>();

        for _ in 0..length {
            res <<= 8u8;
            self.advance_pc();
            let current_byte = self.current_byte().chain_err(|| "unable to read current byte")?;
            if let Some(number) = T::from_u8(current_byte) {
                res |= number;
            } else {
                bail!("unable to convert from u8");
            }

        }

        Ok(res)
    }
}

#[derive(Default)]
struct StackData {
    /// The stack pointer
    ptr: Address,
    data: Vec<Word>,
}

/// The whole state of the VM
pub struct VM {
    /// The buffer registers
    buf_regs: [Word; BUF_REG_COUNT],
    cmp_reg: CompareRegister,
    image: ImageData,
    stack: StackData,
}

impl VM {
    pub fn new() -> VM {
        VM {
            image: ImageData::default(),
            stack: StackData::default(),
            buf_regs: [0; BUF_REG_COUNT],
            cmp_reg: CompareRegister { cra: 0, crb: 0 },
        }
    }

    pub fn exec<P: AsRef<Path>>(&mut self, path: P) -> VMResult<()> {
        self.image.from_path(path)?;

        while self.image.pc < self.image.data.len() {
            let byte = self.image.current_byte().chain_err(|| "unable to read current byte")?;

            match byte {
                bytecode::HALT => break,
                bytecode::ADD => self.add().chain_err(|| "unable to execute 'add' instruction")?,
                bytecode::SUB => self.sub().chain_err(|| "unable to execute 'sub' instruction")?,
                bytecode::MUL => self.mul().chain_err(|| "unable to execute 'mul' instruction")?,
                bytecode::DIV => self.div().chain_err(|| "unable to execute 'div' instruction")?,
                bytecode::PUSH => {
                    let res = self.image.read().chain_err(|| "unable to read word")?;

                    self.push_word(res).chain_err(|| "unable to push value to the stack")?;
                }
                bytecode::JMP => {
                    let addr: Word = self.image.read().chain_err(|| "unable to read word")?;

                    self.image.jmp(addr as Address);
                    continue;
                }
                bytecode::JZ => {
                    let addr: Word = self.image.read().chain_err(|| "unable to read word")?;

                    let top_of_stack = self.peek_number()
                        .chain_err(|| "unable to get current top of stack")?;

                    if top_of_stack == 0.0 {
                        self.image.jmp(addr as Address);
                        continue;
                    }
                }
                bytecode::JNZ => {
                    let addr: Word = self.image.read().chain_err(|| "unable to read word")?;

                    let top_of_stack = self.peek_number()
                        .chain_err(|| "unable to get current top of stack")?;

                    if top_of_stack != 0.0 {
                        self.image.jmp(addr as Address);
                        continue;
                    }
                }
                _ => {
                    bail!(
                        "unexpected opcode {:02x} at address {:?}",
                        byte,
                        self.image.pc
                    )
                }
            }

            self.image.advance_pc();
        }

        Ok(())
    }

    pub fn mount<T: Mountable>(&mut self, device: T) -> VMResult<()> {
        device.run();

        Ok(())
    }

    fn push_word(&mut self, value: Word) -> VMResult<()> {
        if !self.stack.data.is_empty() {
            self.stack.ptr += 1;
        }

        self.stack.data.push(value);

        Ok(())
    }

    fn push_number(&mut self, value: Number) -> VMResult<()> {
        self.push_word(value.bits())
    }

    fn pop_word(&mut self) -> VMResult<Word> {
        if self.stack.data.is_empty() {
            bail!("unable to pop word off an empty Stack");
        }

        let res = self.stack.data.remove(self.stack.ptr);
        if !self.stack.data.is_empty() {
            self.stack.ptr -= 1;
        }

        Ok(res)
    }

    fn pop_number(&mut self) -> VMResult<Number> {
        let top = self.pop_word().chain_err(|| "unable to pop word off the stack")?;
        Ok(Number::from_bits(top))
    }

    fn add(&mut self) -> VMResult<()> {
        let b = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        let a = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        self.push_number(a + b).chain_err(|| "unable to push value to the stack")?;
        Ok(())
    }

    fn sub(&mut self) -> VMResult<()> {
        let b = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        let a = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        self.push_number(a - b).chain_err(|| "unable to push to stack")?;
        Ok(())
    }

    fn mul(&mut self) -> VMResult<()> {
        let b = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        let a = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        self.push_number(a * b).chain_err(|| "unable to push to stack")?;
        Ok(())
    }

    fn div(&mut self) -> VMResult<()> {
        let b = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        let a = self.pop_number().chain_err(|| "unable to pop word off the stack")?;
        self.push_number(a / b).chain_err(|| "unable to push to stack")?;
        Ok(())
    }

    fn peek_word(&mut self) -> VMResult<Word> {
        if self.stack.ptr < self.stack.data.len() {
            Ok(self.stack.data[self.stack.ptr])
        } else {
            bail!("stack pointer out of bounds");
        }
    }

    fn peek_number(&mut self) -> VMResult<Number> {
        let top = self.peek_word().chain_err(|| "unable to peek for word")?;
        Ok(Number::from_bits(top))
    }
}
<|endoftext|>


<commit_before>///! Process syscalls

use core::mem;
use core::str;

use arch;
use arch::paging::{VirtualAddress, entry};
use context;
use elf;
use syscall::{self, Error, Result};

pub fn brk(address: usize) -> Result<usize> {
    let contexts = context::contexts();
    let context_lock = contexts.current().ok_or(Error::NoProcess)?;
    let mut context = context_lock.write();

    let mut current = arch::USER_HEAP_OFFSET;
    if let Some(ref heap) = context.heap {
        current = heap.start_address().get() + heap.size();
    }
    if address == 0 {
        //println!("Brk query {:X}", current);
        Ok(current)
    } else if address >= arch::USER_HEAP_OFFSET {
        //TODO: out of memory errors
        if let Some(ref mut heap) = context.heap {
            heap.resize(address - arch::USER_HEAP_OFFSET, true, true);
            return Ok(address);
        }

        context.heap = Some(context::memory::Memory::new(
            VirtualAddress::new(arch::USER_HEAP_OFFSET),
            address - arch::USER_HEAP_OFFSET,
            entry::WRITABLE | entry::NO_EXECUTE | entry::USER_ACCESSIBLE,
            true,
            true
        ));

        Ok(address)
    } else {
        //TODO: Return correct error
        Err(Error::NotPermitted)
    }
}

pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
    println!("Clone {:X}: {:X}", flags, stack_base);

    let arch;
    let mut kstack_option = None;
    let mut offset = 0;
    let mut stack_option = None;

    // Copy from old process
    {
        let contexts = context::contexts();
        let context_lock = contexts.current().ok_or(Error::NoProcess)?;
        let context = context_lock.read();
        arch = context.arch.clone();
        if let Some(ref stack) = context.kstack {
            offset = stack_base - stack.as_ptr() as usize - mem::size_of::<usize>(); // Add clone ret
            let mut new_stack = stack.clone();
            unsafe {
                let func_ptr = new_stack.as_mut_ptr().offset(offset as isize);
                *(func_ptr as *mut usize) = arch::interrupt::syscall::clone_ret as usize;
            }
            kstack_option = Some(new_stack);
        }
        if let Some(ref stack) = context.stack {
            let mut new_stack = context::memory::Memory::new(
                VirtualAddress::new(arch::USER_TMP_STACK_OFFSET),
                stack.size(),
                entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE,
                true,
                true //TODO: Don't clear stack?
            );
            unsafe {
                arch::externs::memcpy(new_stack.start_address().get() as *mut u8,
                                      stack.start_address().get() as *const u8,
                                      stack.size());
            }
            stack_option = Some(new_stack);
        }
    }

    // Set up new process
    let pid;
    {
        let mut contexts = context::contexts_mut();
        let context_lock = contexts.new_context()?;
        let mut context = context_lock.write();
        context.arch = arch;
        if let Some(stack) = kstack_option.take() {
            context.arch.set_stack(stack.as_ptr() as usize + offset);
            context.kstack = Some(stack);
        }
        if let Some(mut stack) = stack_option.take() {
            //stack.replace(VirtualAddress::new(arch::USER_STACK_OFFSET), true);
            context.stack = Some(stack);
        }
        context.blocked = false;
        pid = context.id;
    }

    //unsafe { context::switch(); }

    Ok(pid)
}

pub fn exit(status: usize) -> ! {
    println!("Exit {}", status);

    {
        let contexts = context::contexts();
        let context_lock = contexts.current().expect("tried to exit without context");
        let mut context = context_lock.write();
        context.image.clear();
        drop(context.heap.take());
        drop(context.stack.take());
        context.exited = true;
    }

    unsafe { context::switch(); }

    unreachable!();
}

pub fn exec(path: &[u8], _args: &[[usize; 2]]) -> Result<usize> {
    //TODO: Use args
    //TODO: Unmap previous mappings
    //TODO: Drop data vec
    println!("Exec {}", unsafe { str::from_utf8_unchecked(path) });

    let file = syscall::open(path, 0)?;
    let mut data = vec![];
    loop {
        let mut buf = [0; 4096];
        let count = syscall::read(file, &mut buf)?;
        if count > 0 {
            data.extend_from_slice(&buf[..count]);
        } else {
            break;
        }
    }
    let _ = syscall::close(file);

    match elf::Elf::from(&data) {
        Ok(elf) => elf.run().and(Ok(0)),
        Err(err) => {
            println!("failed to execute {}: {}", unsafe { str::from_utf8_unchecked(path) }, err);
            Err(Error::NoExec)
        }
    }
}

pub fn getpid() -> Result<usize> {
    let contexts = context::contexts();
    let context_lock = contexts.current().ok_or(Error::NoProcess)?;
    let context = context_lock.read();
    Ok(context.id)
}

pub fn iopl(_level: usize) -> Result<usize> {
    //TODO
    Ok(0)
}

pub fn sched_yield() -> Result<usize> {
    unsafe { context::switch(); }
    Ok(0)
}
<commit_msg>Higher-half kernel mapping. Unmap where possible, freeing up lower memory<commit_after>///! Process syscalls

use core::mem;
use core::str;

use arch;
use arch::paging::{VirtualAddress, entry};
use context;
use elf;
use syscall::{self, Error, Result};

pub fn brk(address: usize) -> Result<usize> {
    let contexts = context::contexts();
    let context_lock = contexts.current().ok_or(Error::NoProcess)?;
    let mut context = context_lock.write();

    let mut current = arch::USER_HEAP_OFFSET;
    if let Some(ref heap) = context.heap {
        current = heap.start_address().get() + heap.size();
    }
    if address == 0 {
        //println!("Brk query {:X}", current);
        Ok(current)
    } else if address >= arch::USER_HEAP_OFFSET {
        //TODO: out of memory errors
        if let Some(ref mut heap) = context.heap {
            heap.resize(address - arch::USER_HEAP_OFFSET, true, true);
            return Ok(address);
        }

        context.heap = Some(context::memory::Memory::new(
            VirtualAddress::new(arch::USER_HEAP_OFFSET),
            address - arch::USER_HEAP_OFFSET,
            entry::WRITABLE | entry::NO_EXECUTE | entry::USER_ACCESSIBLE,
            true,
            true
        ));

        Ok(address)
    } else {
        //TODO: Return correct error
        Err(Error::NotPermitted)
    }
}

pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
    println!("Clone {:X}: {:X}", flags, stack_base);

    let arch;
    let mut kstack_option = None;
    let mut offset = 0;
    let mut stack_option = None;

    // Copy from old process
    {
        let contexts = context::contexts();
        let context_lock = contexts.current().ok_or(Error::NoProcess)?;
        let context = context_lock.read();
        arch = context.arch.clone();
        if let Some(ref stack) = context.kstack {
            offset = stack_base - stack.as_ptr() as usize - mem::size_of::<usize>(); // Add clone ret
            let mut new_stack = stack.clone();
            unsafe {
                let func_ptr = new_stack.as_mut_ptr().offset(offset as isize);
                *(func_ptr as *mut usize) = arch::interrupt::syscall::clone_ret as usize;
            }
            kstack_option = Some(new_stack);
        }
        if let Some(ref stack) = context.stack {
            let mut new_stack = context::memory::Memory::new(
                VirtualAddress::new(arch::USER_TMP_STACK_OFFSET),
                stack.size(),
                entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE,
                true,
                true //TODO: Don't clear stack?
            );
            unsafe {
                arch::externs::memcpy(new_stack.start_address().get() as *mut u8,
                                      stack.start_address().get() as *const u8,
                                      stack.size());
            }
            new_stack.unmap(true);
            stack_option = Some(new_stack);
        }
    }

    // Set up new process
    let pid;
    {
        let mut contexts = context::contexts_mut();
        let context_lock = contexts.new_context()?;
        let mut context = context_lock.write();
        context.arch = arch;
        if let Some(stack) = kstack_option.take() {
            context.arch.set_stack(stack.as_ptr() as usize + offset);
            context.kstack = Some(stack);
        }
        if let Some(mut stack) = stack_option.take() {
            //stack.replace(VirtualAddress::new(arch::USER_STACK_OFFSET), true);
            context.stack = Some(stack);
        }
        context.blocked = false;
        pid = context.id;
    }

    //unsafe { context::switch(); }

    Ok(pid)
}

pub fn exit(status: usize) -> ! {
    println!("Exit {}", status);

    {
        let contexts = context::contexts();
        let context_lock = contexts.current().expect("tried to exit without context");
        let mut context = context_lock.write();
        context.image.clear();
        drop(context.heap.take());
        drop(context.stack.take());
        context.exited = true;
    }

    unsafe { context::switch(); }

    unreachable!();
}

pub fn exec(path: &[u8], _args: &[[usize; 2]]) -> Result<usize> {
    //TODO: Use args
    //TODO: Unmap previous mappings
    //TODO: Drop data vec
    println!("Exec {}", unsafe { str::from_utf8_unchecked(path) });

    let file = syscall::open(path, 0)?;
    let mut data = vec![];
    loop {
        let mut buf = [0; 4096];
        let count = syscall::read(file, &mut buf)?;
        if count > 0 {
            data.extend_from_slice(&buf[..count]);
        } else {
            break;
        }
    }
    let _ = syscall::close(file);

    match elf::Elf::from(&data) {
        Ok(elf) => elf.run().and(Ok(0)),
        Err(err) => {
            println!("failed to execute {}: {}", unsafe { str::from_utf8_unchecked(path) }, err);
            Err(Error::NoExec)
        }
    }
}

pub fn getpid() -> Result<usize> {
    let contexts = context::contexts();
    let context_lock = contexts.current().ok_or(Error::NoProcess)?;
    let context = context_lock.read();
    Ok(context.id)
}

pub fn iopl(_level: usize) -> Result<usize> {
    //TODO
    Ok(0)
}

pub fn sched_yield() -> Result<usize> {
    unsafe { context::switch(); }
    Ok(0)
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use std::collections::HashSet;
use std::iter::FromIterator;
use calx_grid::{Dir6, HexFov};
use calx_ecs::Entity;
use calx_resource::{Resource, ResourceStore};
use world::World;
use components::{Alignment, BrainState};
use stats::Intrinsic;
use location::Location;
use brush::Brush;
use stats;
use FovStatus;
use fov::SightFov;
use terraform::TerrainQuery;
use world::Ecs;
use terrain;
use form;
use ::Prefab;

/// Immutable querying of game world state.
pub trait Query: TerrainQuery {
    /// Return the location of an entity.
    ///
    /// Returns the location of the containing entity for entities inside
    /// containers. It is possible for entities to not have a location.
    fn location(&self, e: Entity) -> Option<Location>;

    /// Return the player entity if one exists.
    fn player(&self) -> Option<Entity>;

    /// Return current time of the world logic clock.
    fn tick(&self) -> u64;

    /// Return world RNG seed
    fn rng_seed(&self) -> u32;

    /// Return maximum health of an entity.
    fn max_hp(&self, e: Entity) -> i32 { self.stats(e).power }

    // XXX: Would be nicer if entities_at returned an iterator. Probably want to wait for impl
    // Trait return types before jumping to this.

    /// Return an iterator to entities at the given location.
    fn entities_at(&self, loc: Location) -> Vec<Entity>;

    /// Return reference to the world entity component system.
    fn ecs<'a>(&'a self) -> &'a Ecs;

    /// Return the AI state of an entity.
    fn brain_state(&self, e: Entity) -> Option<BrainState> {
        self.ecs().brain.get(e).map_or(None, |brain| Some(brain.state))
    }

    /// Return whether the entity is a mobile object (eg. active creature).
    fn is_mob(&self, e: Entity) -> bool { self.ecs().brain.contains(e) }

    /// Return the value for how a mob will react to other mobs.
    fn alignment(&self, e: Entity) -> Option<Alignment> {
        self.ecs().brain.get(e).map(|b| b.alignment)
    }

    /// Return current health of an entity.
    fn hp(&self, e: Entity) -> i32 {
        self.max_hp(e) - if self.ecs().health.contains(e) { self.ecs().health[e].wounds } else { 0 }
    }

    /// Return field of view for a location.
    fn fov_status(&self, loc: Location) -> Option<FovStatus> {
        if let Some(p) = self.player() {
            if self.ecs().map_memory.contains(p) {
                if self.ecs().map_memory[p].seen.contains(&loc) {
                    return Some(FovStatus::Seen);
                }
                if self.ecs().map_memory[p].remembered.contains(&loc) {
                    return Some(FovStatus::Remembered);
                }
                return None;
            }
        }
        // Just show everything by default.
        Some(FovStatus::Seen)
    }

    /// Return visual brush for an entity.
    fn entity_brush(&self, e: Entity) -> Option<Resource<Brush>> {
        self.ecs().desc.get(e).map(|x| x.brush.clone())
    }

    /// Return the (composite) stats for an entity.
    ///
    /// Will return the default value for the Stats type (additive identity in the stat algebra)
    /// for entities that have no stats component defined.
    fn stats(&self, e: Entity) -> stats::Stats {
        self.ecs().composite_stats.get(e).map_or_else(|| self.base_stats(e), |x| x.0)
    }

    /// Return the base stats of the entity. Does not include any added effects.
    ///
    /// You usually want to use the `stats` method instead of this one.
    fn base_stats(&self, e: Entity) -> stats::Stats {
        self.ecs().stats.get(e).cloned().unwrap_or_default()
    }

    /// Return whether the entity can move in a direction.
    fn can_step(&self, e: Entity, dir: Dir6) -> bool {
        self.location(e).map_or(false, |loc| self.can_enter(e, loc + dir.to_v2()))
    }

    /// Return whether location blocks line of sight.
    fn blocks_sight(&self, loc: Location) -> bool { self.terrain(loc).blocks_sight() }

    /// Return whether the entity can occupy a location.
    fn can_enter(&self, e: Entity, loc: Location) -> bool {
        if self.terrain(loc).is_door() && !self.has_intrinsic(e, Intrinsic::Hands) {
            // Can't open doors without hands.
            return false;
        }
        if self.blocks_walk(loc) {
            return false;
        }
        true
    }

    /// Return whether the entity blocks movement of other entities.
    fn is_blocking_entity(&self, e: Entity) -> bool { self.is_mob(e) }

    /// Return whether the location obstructs entity movement.
    fn blocks_walk(&self, loc: Location) -> bool {
        if self.terrain(loc).blocks_walk() {
            return true;
        }
        if self.entities_at(loc)
               .into_iter()
               .any(|e| self.is_blocking_entity(e)) {
            return true;
        }
        false
    }

    /// Return whether a location contains mobs.
    fn has_mobs(&self, loc: Location) -> bool { self.mob_at(loc).is_some() }

    /// Return mob (if any) at given position.
    fn mob_at(&self, loc: Location) -> Option<Entity> {
        self.entities_at(loc).into_iter().find(|&e| self.is_mob(e))
    }

    /// Return whether the entity has a specific intrinsic property (eg. poison resistance).
    fn has_intrinsic(&self, e: Entity, intrinsic: Intrinsic) -> bool {
        self.stats(e).intrinsics & intrinsic as u32 != 0
    }

    /// Return if the entity is a mob that should get an update this frame
    /// based on its speed properties. Does not check for status effects like
    /// sleep that might prevent actual action.
    fn ticks_this_frame(&self, e: Entity) -> bool {
        if !self.is_mob(e) || !self.is_alive(e) {
            return false;
        }

        // Go through a cycle of 5 phases to get 4 possible speeds.
        // System idea from Jeff Lait.
        let phase = self.tick() % 5;
        match phase {
            0 => return true,
            1 => return self.has_intrinsic(e, Intrinsic::Fast),
            2 => return true,
            3 => return self.has_intrinsic(e, Intrinsic::Quick),
            4 => return !self.has_intrinsic(e, Intrinsic::Slow),
            _ => panic!("Invalid action phase"),
        }
    }

    /// Return whether the entity is dead and should be removed from the world.
    fn is_alive(&self, e: Entity) -> bool { self.location(e).is_some() }

    /// Return true if the game has ended and the player can make no further
    /// actions.
    fn game_over(&self) -> bool { self.player().is_none() }

    /// Return whether an entity is the player avatar mob.
    fn is_player(&self, e: Entity) -> bool {
        // TODO: Should this just check self.flags.player?
        self.brain_state(e) == Some(BrainState::PlayerControl) && self.is_alive(e)
    }

    /// Return whether the entity is an awake mob.
    fn is_active(&self, e: Entity) -> bool {
        match self.brain_state(e) {
            Some(BrainState::Asleep) => false,
            Some(_) => true,
            _ => false,
        }
    }

    /// Return whether the entity is a mob that will act this frame.
    fn acts_this_frame(&self, e: Entity) -> bool {
        if !self.is_active(e) {
            return false;
        }
        return self.ticks_this_frame(e);
    }

    /// Look for targets to shoot in a direction.
    fn find_target(&self, shooter: Entity, dir: Dir6, range: usize) -> Option<Entity> {
        let origin = self.location(shooter).unwrap();
        for i in 1..(range + 1) {
            let loc = origin + dir.to_v2() * (i as i32);
            if self.terrain(loc).blocks_shot() {
                break;
            }
            if let Some(e) = self.mob_at(loc) {
                if self.is_hostile_to(shooter, e) {
                    return Some(e);
                }
            }
        }
        None
    }

    /// Return whether the entity wants to fight the other entity.
    fn is_hostile_to(&self, e: Entity, other: Entity) -> bool {
        match (self.alignment(e), self.alignment(other)) {
            (Some(Alignment::Chaotic), Some(_)) => true,
            (Some(_), Some(Alignment::Chaotic)) => true,
            (Some(Alignment::Evil), Some(Alignment::Good)) => true,
            (Some(Alignment::Good), Some(Alignment::Evil)) => true,
            _ => false,
        }
    }

    /// Return whether the entity should have an idle animation.
    fn is_bobbing(&self, e: Entity) -> bool { self.is_active(e) && !self.is_player(e) }

    /// Return the field of view chart for visible tiles.
    fn sight_fov(w: &World, origin: Location, range: u32) -> HashSet<Location> {
        HashSet::from_iter(HexFov::new(SightFov::new(w, range, origin))
                               .map(|(pos, a)| a.origin + pos))
    }

    /// Return Id value of terrain at location for drawing on screen.
    fn visual_terrain_id(&self, loc: Location) -> u8 {
        let mut idx = self.terrain_id(loc);

        if idx == terrain::Id::Door as u8 {
            // Standing in the doorway opens the door.
            if self.has_mobs(loc) {
                idx = terrain::Id::OpenDoor as u8;
            }
        }

        // TODO: Might want a more generic method of specifying cosmetic terrain variants.
        if idx == terrain::Id::Grass as u8 {
            // Grass is occasionally fancy.
            if loc.noise() > 0.85 {
                idx = terrain::Id::Grass2 as u8;
            }
        }

        idx
    }

    /// Return terrain at location for drawing on screen.
    ///
    /// Terrain is sometimes replaced with a variant for visual effect, but
    /// this should not be reflected in the logical terrain.
    fn visual_terrain(&self, loc: Location) -> Arc<terrain::Tile> {
        terrain::Tile::get_resource(&self.visual_terrain_id(loc)).unwrap()
    }

    /// Return the name that can be used to spawn this entity.
    fn spawn_name<'a>(&'a self, e: Entity) -> Option<&'a str> {
        // TODO: Create a special component for this.
        self.ecs().desc.get(e).map_or(None, |ref desc| Some(&desc.name[..]))
    }

    fn is_spawn_name(&self, spawn_name: &str) -> bool {
        form::FORMS.iter().position(|f| f.name() == Some(spawn_name)).is_some()
    }

    fn extract_prefab<I: IntoIterator<Item=Location>>(&self, locs: I) -> Prefab {
        let mut map = Vec::new();
        let mut origin = None;

        for loc in locs {
            // Store first location as an arbitrary origin.
            let origin = match origin {
                None => { origin = Some(loc); loc }
                Some(origin) => origin,
            };

            let pos = origin.v2_at(loc).expect("Trying to build prefab from multiple z-levels");

            let terrain = terrain::Id::from_u8(self.terrain_id(loc)).expect("Corrupt terrain");

            let entities = Vec::from_iter(
                self.entities_at(loc).into_iter().filter_map(|e| self.spawn_name(e).map(|s| s.to_string())));

            map.push((pos, (terrain, entities)));
        }

        Prefab::from_iter(map.into_iter())
    }
}
<commit_msg>Mobs can't walk offscreen<commit_after>use std::sync::Arc;
use std::collections::HashSet;
use std::iter::FromIterator;
use calx_grid::{Dir6, HexFov};
use calx_ecs::Entity;
use calx_resource::{Resource, ResourceStore};
use world::World;
use components::{Alignment, BrainState};
use stats::Intrinsic;
use location::Location;
use brush::Brush;
use stats;
use FovStatus;
use fov::SightFov;
use terraform::TerrainQuery;
use world::Ecs;
use terrain;
use form;
use Prefab;

/// Immutable querying of game world state.
pub trait Query: TerrainQuery {
    /// Return the location of an entity.
    ///
    /// Returns the location of the containing entity for entities inside
    /// containers. It is possible for entities to not have a location.
    fn location(&self, e: Entity) -> Option<Location>;

    /// Return the player entity if one exists.
    fn player(&self) -> Option<Entity>;

    /// Return current time of the world logic clock.
    fn tick(&self) -> u64;

    /// Return world RNG seed
    fn rng_seed(&self) -> u32;

    /// Return maximum health of an entity.
    fn max_hp(&self, e: Entity) -> i32 { self.stats(e).power }

    // XXX: Would be nicer if entities_at returned an iterator. Probably want to wait for impl
    // Trait return types before jumping to this.

    /// Return an iterator to entities at the given location.
    fn entities_at(&self, loc: Location) -> Vec<Entity>;

    /// Return reference to the world entity component system.
    fn ecs<'a>(&'a self) -> &'a Ecs;

    /// Return the AI state of an entity.
    fn brain_state(&self, e: Entity) -> Option<BrainState> {
        self.ecs().brain.get(e).map_or(None, |brain| Some(brain.state))
    }

    /// Return whether the entity is a mobile object (eg. active creature).
    fn is_mob(&self, e: Entity) -> bool { self.ecs().brain.contains(e) }

    /// Return the value for how a mob will react to other mobs.
    fn alignment(&self, e: Entity) -> Option<Alignment> {
        self.ecs().brain.get(e).map(|b| b.alignment)
    }

    /// Return current health of an entity.
    fn hp(&self, e: Entity) -> i32 {
        self.max_hp(e) - if self.ecs().health.contains(e) { self.ecs().health[e].wounds } else { 0 }
    }

    /// Return field of view for a location.
    fn fov_status(&self, loc: Location) -> Option<FovStatus> {
        if let Some(p) = self.player() {
            if self.ecs().map_memory.contains(p) {
                if self.ecs().map_memory[p].seen.contains(&loc) {
                    return Some(FovStatus::Seen);
                }
                if self.ecs().map_memory[p].remembered.contains(&loc) {
                    return Some(FovStatus::Remembered);
                }
                return None;
            }
        }
        // Just show everything by default.
        Some(FovStatus::Seen)
    }

    /// Return visual brush for an entity.
    fn entity_brush(&self, e: Entity) -> Option<Resource<Brush>> {
        self.ecs().desc.get(e).map(|x| x.brush.clone())
    }

    /// Return the (composite) stats for an entity.
    ///
    /// Will return the default value for the Stats type (additive identity in the stat algebra)
    /// for entities that have no stats component defined.
    fn stats(&self, e: Entity) -> stats::Stats {
        self.ecs().composite_stats.get(e).map_or_else(|| self.base_stats(e), |x| x.0)
    }

    /// Return the base stats of the entity. Does not include any added effects.
    ///
    /// You usually want to use the `stats` method instead of this one.
    fn base_stats(&self, e: Entity) -> stats::Stats {
        self.ecs().stats.get(e).cloned().unwrap_or_default()
    }

    /// Return whether the entity can move in a direction.
    fn can_step(&self, e: Entity, dir: Dir6) -> bool {
        self.location(e).map_or(false, |loc| self.can_enter(e, loc + dir.to_v2()))
    }

    /// Return whether location blocks line of sight.
    fn blocks_sight(&self, loc: Location) -> bool { self.terrain(loc).blocks_sight() }

    /// Return whether the entity can occupy a location.
    fn can_enter(&self, e: Entity, loc: Location) -> bool {
        if self.terrain(loc).is_door() && !self.has_intrinsic(e, Intrinsic::Hands) {
            // Can't open doors without hands.
            return false;
        }
        if self.blocks_walk(loc) {
            return false;
        }
        true
    }

    /// Return whether the entity blocks movement of other entities.
    fn is_blocking_entity(&self, e: Entity) -> bool { self.is_mob(e) }

    /// Return whether the location obstructs entity movement.
    fn blocks_walk(&self, loc: Location) -> bool {
        if !self.is_valid_location(loc) {
            return true;
        }
        if self.terrain(loc).blocks_walk() {
            return true;
        }
        if self.entities_at(loc)
               .into_iter()
               .any(|e| self.is_blocking_entity(e)) {
            return true;
        }
        false
    }

    /// Return whether a location contains mobs.
    fn has_mobs(&self, loc: Location) -> bool { self.mob_at(loc).is_some() }

    /// Return mob (if any) at given position.
    fn mob_at(&self, loc: Location) -> Option<Entity> {
        self.entities_at(loc).into_iter().find(|&e| self.is_mob(e))
    }

    /// Return whether the entity has a specific intrinsic property (eg. poison resistance).
    fn has_intrinsic(&self, e: Entity, intrinsic: Intrinsic) -> bool {
        self.stats(e).intrinsics & intrinsic as u32 != 0
    }

    /// Return if the entity is a mob that should get an update this frame
    /// based on its speed properties. Does not check for status effects like
    /// sleep that might prevent actual action.
    fn ticks_this_frame(&self, e: Entity) -> bool {
        if !self.is_mob(e) || !self.is_alive(e) {
            return false;
        }

        // Go through a cycle of 5 phases to get 4 possible speeds.
        // System idea from Jeff Lait.
        let phase = self.tick() % 5;
        match phase {
            0 => return true,
            1 => return self.has_intrinsic(e, Intrinsic::Fast),
            2 => return true,
            3 => return self.has_intrinsic(e, Intrinsic::Quick),
            4 => return !self.has_intrinsic(e, Intrinsic::Slow),
            _ => panic!("Invalid action phase"),
        }
    }

    /// Return whether the entity is dead and should be removed from the world.
    fn is_alive(&self, e: Entity) -> bool { self.location(e).is_some() }

    /// Return true if the game has ended and the player can make no further
    /// actions.
    fn game_over(&self) -> bool { self.player().is_none() }

    /// Return whether an entity is the player avatar mob.
    fn is_player(&self, e: Entity) -> bool {
        // TODO: Should this just check self.flags.player?
        self.brain_state(e) == Some(BrainState::PlayerControl) && self.is_alive(e)
    }

    /// Return whether the entity is an awake mob.
    fn is_active(&self, e: Entity) -> bool {
        match self.brain_state(e) {
            Some(BrainState::Asleep) => false,
            Some(_) => true,
            _ => false,
        }
    }

    /// Return whether the entity is a mob that will act this frame.
    fn acts_this_frame(&self, e: Entity) -> bool {
        if !self.is_active(e) {
            return false;
        }
        return self.ticks_this_frame(e);
    }

    /// Look for targets to shoot in a direction.
    fn find_target(&self, shooter: Entity, dir: Dir6, range: usize) -> Option<Entity> {
        let origin = self.location(shooter).unwrap();
        for i in 1..(range + 1) {
            let loc = origin + dir.to_v2() * (i as i32);
            if self.terrain(loc).blocks_shot() {
                break;
            }
            if let Some(e) = self.mob_at(loc) {
                if self.is_hostile_to(shooter, e) {
                    return Some(e);
                }
            }
        }
        None
    }

    /// Return whether the entity wants to fight the other entity.
    fn is_hostile_to(&self, e: Entity, other: Entity) -> bool {
        match (self.alignment(e), self.alignment(other)) {
            (Some(Alignment::Chaotic), Some(_)) => true,
            (Some(_), Some(Alignment::Chaotic)) => true,
            (Some(Alignment::Evil), Some(Alignment::Good)) => true,
            (Some(Alignment::Good), Some(Alignment::Evil)) => true,
            _ => false,
        }
    }

    /// Return whether the entity should have an idle animation.
    fn is_bobbing(&self, e: Entity) -> bool { self.is_active(e) && !self.is_player(e) }

    /// Return the field of view chart for visible tiles.
    fn sight_fov(w: &World, origin: Location, range: u32) -> HashSet<Location> {
        HashSet::from_iter(HexFov::new(SightFov::new(w, range, origin))
                               .map(|(pos, a)| a.origin + pos))
    }

    /// Return Id value of terrain at location for drawing on screen.
    fn visual_terrain_id(&self, loc: Location) -> u8 {
        let mut idx = self.terrain_id(loc);

        if idx == terrain::Id::Door as u8 {
            // Standing in the doorway opens the door.
            if self.has_mobs(loc) {
                idx = terrain::Id::OpenDoor as u8;
            }
        }

        // TODO: Might want a more generic method of specifying cosmetic terrain variants.
        if idx == terrain::Id::Grass as u8 {
            // Grass is occasionally fancy.
            if loc.noise() > 0.85 {
                idx = terrain::Id::Grass2 as u8;
            }
        }

        idx
    }

    /// Return terrain at location for drawing on screen.
    ///
    /// Terrain is sometimes replaced with a variant for visual effect, but
    /// this should not be reflected in the logical terrain.
    fn visual_terrain(&self, loc: Location) -> Arc<terrain::Tile> {
        terrain::Tile::get_resource(&self.visual_terrain_id(loc)).unwrap()
    }

    /// Return the name that can be used to spawn this entity.
    fn spawn_name<'a>(&'a self, e: Entity) -> Option<&'a str> {
        // TODO: Create a special component for this.
        self.ecs().desc.get(e).map_or(None, |ref desc| Some(&desc.name[..]))
    }

    fn is_spawn_name(&self, spawn_name: &str) -> bool {
        form::FORMS.iter().position(|f| f.name() == Some(spawn_name)).is_some()
    }

    fn extract_prefab<I: IntoIterator<Item=Location>>(&self, locs: I) -> Prefab {
        let mut map = Vec::new();
        let mut origin = None;

        for loc in locs {
            // Store first location as an arbitrary origin.
            let origin = match origin {
                None => { origin = Some(loc); loc }
                Some(origin) => origin,
            };

            let pos = origin.v2_at(loc).expect("Trying to build prefab from multiple z-levels");

            let terrain = terrain::Id::from_u8(self.terrain_id(loc)).expect("Corrupt terrain");

            let entities = Vec::from_iter(
                self.entities_at(loc).into_iter().filter_map(|e| self.spawn_name(e).map(|s| s.to_string())));

            map.push((pos, (terrain, entities)));
        }

        Prefab::from_iter(map.into_iter())
    }
}
<|endoftext|>


<commit_before>// xfail-stage0

use std;
import std::ivec;
import std::int;
import std::sort;

fn test_qsort() {
    let names = ~[mutable 2, 1, 3];

    let expected = ~[1, 2, 3];

    fn lteq(a: &int, b: &int) -> bool { int::le(a, b) }
    sort::ivector::quick_sort(lteq, names);

    let pairs = ivec::zip(expected, ivec::from_mut(names));
    for p: {_0: int, _1: int}  in pairs {
        log_err #fmt("%d %d", p._0, p._1);
        assert (p._0 == p._1);
    }
}

fn main() { test_qsort(); }<commit_msg>Remove test/run-pass/simple-qsort<commit_after><|endoftext|>


<commit_before>// issue-38940: error printed twice for deref recursion limit exceeded
// Test that the recursion limit can be changed. In this case, we have
// deeply nested types that will fail the `Send` check by overflow
// when the recursion limit is set very low.
#![allow(dead_code)]
#![recursion_limit="10"]
macro_rules! link {
    ($outer:ident, $inner:ident) => {
        struct $outer($inner);
        impl $outer {
            fn new() -> $outer {
                $outer($inner::new())
            }
        }
        impl std::ops::Deref for $outer {
            type Target = $inner;
            fn deref(&self) -> &$inner {
                &self.0
            }
        }
    }
}
struct Bottom;
impl Bottom {
    fn new() -> Bottom {
        Bottom
    }
}
link!(Top, A);
link!(A, B);
link!(B, C);
link!(C, D);
link!(D, E);
link!(E, F);
link!(F, G);
link!(G, H);
link!(H, I);
link!(I, J);
link!(J, K);
link!(K, Bottom);
fn main() {
    let t = Top::new();
    let x: &Bottom = &t;
    //~^ ERROR mismatched types
    //~| NOTE expected type `&Bottom`
    //~| NOTE found type `&Top`
    //~| NOTE expected struct `Bottom`, found struct `Top`
    //~| ERROR reached the recursion limit while auto-dereferencing I
    //~| NOTE deref recursion limit reached
    //~| NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
}
<commit_msg>Remove incidental notes<commit_after>// issue-38940: error printed twice for deref recursion limit exceeded
// Test that the recursion limit can be changed. In this case, we have
// deeply nested types that will fail the `Send` check by overflow
// when the recursion limit is set very low.
#![allow(dead_code)]
#![recursion_limit="10"]
macro_rules! link {
    ($outer:ident, $inner:ident) => {
        struct $outer($inner);
        impl $outer {
            fn new() -> $outer {
                $outer($inner::new())
            }
        }
        impl std::ops::Deref for $outer {
            type Target = $inner;
            fn deref(&self) -> &$inner {
                &self.0
            }
        }
    }
}
struct Bottom;
impl Bottom {
    fn new() -> Bottom {
        Bottom
    }
}
link!(Top, A);
link!(A, B);
link!(B, C);
link!(C, D);
link!(D, E);
link!(E, F);
link!(F, G);
link!(G, H);
link!(H, I);
link!(I, J);
link!(J, K);
link!(K, Bottom);
fn main() {
    let t = Top::new();
    let x: &Bottom = &t;
    //~^ ERROR mismatched types
    //~| ERROR reached the recursion limit while auto-dereferencing I
}
<|endoftext|>