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

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

use sys::Configuration;
use types::{Matrix3, Vector3D, Zero};
use consts::ELCC;
use energy::{PairRestriction, RestrictionInfo};
use parallel::prelude::*;
use parallel::ThreadLocalStore;

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

/// Wolf summation for coulombic interactions.
///
/// This is a fast, direct, pairwise summation for coulombic potential
/// [Wolf1999].
///
/// # Examples
///
/// ```
/// use lumol_core::energy::Wolf;
/// use lumol_core::units;
///
/// // A relatively large cutoff is needed for Wolf summation
/// let wolf = Wolf::new(12.0);
///
/// use lumol_core::sys::System;
/// use lumol_core::sys::Particle;
/// use lumol_core::sys::UnitCell;
/// use lumol_core::types::Vector3D;
///
/// // Setup a system containing a NaCl pair
/// let mut system = System::with_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.set_coulomb_potential(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, config: &Configuration, 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
        let charges = config.particles().charge;
        let positions = config.particles().position;
        for (idx, &i) in idxes.iter().enumerate() {
            let qi = charges[i];
            if qi == 0.0 {continue;}
            for j in (0..config.size()).filter(|x| !idxes.contains(x)) {
                let qj = charges[j];
                if qj == 0.0 {continue;}

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

                let distance = config.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 = charges[i];
            if qi == 0.0 {continue;}
            for (jdx, &j) in idxes.iter().enumerate().skip(idx + 1) {
                let qj = charges[j];
                if qj == 0.0 {continue;}

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

                let distance = config.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, configuration: &Configuration) -> f64 {
        let natoms = configuration.size();
        let charges = configuration.particles().charge;

        (0..natoms).par_map(|i| {
            let mut local_energy = 0.0;
            let qi = charges[i];
            if qi == 0.0 { return 0.0; }

            for j in i+1..natoms {
                let qj = charges[j];
                if qj == 0.0 {continue}

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

                let rij = configuration.distance(i, j);
                local_energy  += self.energy_pair(info, qi, qj, rij);
            }

            local_energy - self.energy_self(qi)
        }).sum()
    }

    fn forces(&self, configuration: &Configuration, forces: &mut [Vector3D])  {
        assert_eq!(forces.len(), configuration.size());

        // To avoid race conditions, each thread needs its
        // own local forces Vec
        let natoms = configuration.size();
        let charges = configuration.particles().charge;
        let thread_forces_store = ThreadLocalStore::new(|| vec![Vector3D::zero(); natoms]);

        (0..natoms).into_par_iter().for_each(|i| {
            // Get the thread local forces Vec
            let mut thread_forces = thread_forces_store.borrow_mut();

            let qi = charges[i];
            if qi == 0.0 { return; }
            for j in i + 1..natoms {
                let qj = charges[j];
                if qj == 0.0 { continue }

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

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

        // At this point all the forces are computed, but the
        // results are scattered across all thread local Vecs,
        // here we gather them.
        thread_forces_store.sum_local_values(forces);
    }

    fn virial(&self, configuration: &Configuration) -> Matrix3 {
        let natoms = configuration.size();
        let charges = configuration.particles().charge;

        (0..natoms).par_map(|i| {
            let qi = charges[i];
            if qi == 0.0 { return Matrix3::zero(); }
            let mut local_virial = Matrix3::zero();

            for j in i+1..natoms {
                let qj = charges[j];
                if qj == 0.0 {continue}

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

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

            local_virial
        }).sum()
    }
}

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

#[cfg(test)]
mod tests {
    pub use super::*;
    use sys::System;
    use energy::GlobalPotential;
    use utils::system_from_xyz;

    const E_BRUTE_FORCE: f64 = -0.09262397663346732;

    pub fn testing_system() -> System {
        let mut system = system_from_xyz("2
        cell: 20.0
        Cl 0.0 0.0 0.0
        Na 1.5 0.0 0.0
        ");
        system.particles_mut().charge[0] = -1.0;
        system.particles_mut().charge[1] = 1.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 mut forces = vec![Vector3D::zero(); system.size()];
        wolf.forces(&system, &mut forces);
        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.particles_mut().position[0][0] += eps;

        let e1 = wolf.energy(&system);
        let mut forces = vec![Vector3D::zero(); system.size()];
        wolf.forces(&system, &mut forces);
        assert_relative_eq!((e - e1) / eps, forces[0][0], 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 cell: 20.0
            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
            ");
            assert!(system.molecules().len() == 2);

            for particle in system.particles_mut() {
                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.particles_mut().position[0] = newpos[0];
            system.particles_mut().position[1] = newpos[1];
            let new_e = check.energy(&system);
            assert_ulps_eq!(cost, new_e - old_e);
        }
    }
}
<commit_msg>Do not pass the two charges separatly in Wolf<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) Lumol's contributors — BSD license

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

use sys::Configuration;
use types::{Matrix3, Vector3D, Zero};
use consts::ELCC;
use energy::{PairRestriction, RestrictionInfo};
use parallel::prelude::*;
use parallel::ThreadLocalStore;

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

/// Wolf summation for coulombic interactions.
///
/// This is a fast, direct, pairwise summation for coulombic potential
/// [Wolf1999].
///
/// # Examples
///
/// ```
/// use lumol_core::energy::Wolf;
/// use lumol_core::units;
///
/// // A relatively large cutoff is needed for Wolf summation
/// let wolf = Wolf::new(12.0);
///
/// use lumol_core::sys::System;
/// use lumol_core::sys::Particle;
/// use lumol_core::sys::UnitCell;
/// use lumol_core::types::Vector3D;
///
/// // Setup a system containing a NaCl pair
/// let mut system = System::with_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.set_coulomb_potential(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, qiqj: f64, rij: f64) -> f64 {
        if rij > self.cutoff || info.excluded {
            return 0.0;
        }
        info.scaling * qiqj * (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, qiqj: 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 * qiqj * (factor - self.force_cst) * rij.normalized() / ELCC;
    }
}

impl GlobalCache for Wolf {
    fn move_particles_cost(&self, config: &Configuration, 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
        let charges = config.particles().charge;
        let positions = config.particles().position;
        for (idx, &i) in idxes.iter().enumerate() {
            let qi = charges[i];
            if qi == 0.0 {continue;}
            for j in (0..config.size()).filter(|x| !idxes.contains(x)) {
                let qj = charges[j];
                if qj == 0.0 {continue;}

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

                let distance = config.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 = charges[i];
            if qi == 0.0 {continue;}
            for (jdx, &j) in idxes.iter().enumerate().skip(idx + 1) {
                let qj = charges[j];
                if qj == 0.0 {continue;}

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

                let distance = config.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, configuration: &Configuration) -> f64 {
        let natoms = configuration.size();
        let charges = configuration.particles().charge;

        (0..natoms).par_map(|i| {
            let mut local_energy = 0.0;
            let qi = charges[i];
            if qi == 0.0 { return 0.0; }

            for j in i+1..natoms {
                let qj = charges[j];
                if qj == 0.0 {continue}

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

                let rij = configuration.distance(i, j);
                local_energy  += self.energy_pair(info, qi * qj, rij);
            }

            local_energy - self.energy_self(qi)
        }).sum()
    }

    fn forces(&self, configuration: &Configuration, forces: &mut [Vector3D])  {
        assert_eq!(forces.len(), configuration.size());

        // To avoid race conditions, each thread needs its
        // own local forces Vec
        let natoms = configuration.size();
        let charges = configuration.particles().charge;
        let thread_forces_store = ThreadLocalStore::new(|| vec![Vector3D::zero(); natoms]);

        (0..natoms).into_par_iter().for_each(|i| {
            // Get the thread local forces Vec
            let mut thread_forces = thread_forces_store.borrow_mut();

            let qi = charges[i];
            if qi == 0.0 { return; }
            for j in i + 1..natoms {
                let qj = charges[j];
                if qj == 0.0 { continue }

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

                let rij = configuration.nearest_image(i, j);
                let force = self.force_pair(info, qi * qj, rij);
                thread_forces[i] += force;
                thread_forces[j] -= force;
            }
        });

        // At this point all the forces are computed, but the
        // results are scattered across all thread local Vecs,
        // here we gather them.
        thread_forces_store.sum_local_values(forces);
    }

    fn virial(&self, configuration: &Configuration) -> Matrix3 {
        let natoms = configuration.size();
        let charges = configuration.particles().charge;

        (0..natoms).par_map(|i| {
            let qi = charges[i];
            if qi == 0.0 { return Matrix3::zero(); }
            let mut local_virial = Matrix3::zero();

            for j in i+1..natoms {
                let qj = charges[j];
                if qj == 0.0 {continue}

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

                let rij = configuration.nearest_image(i, j);
                let force = self.force_pair(info, qi * qj, rij);
                local_virial += force.tensorial(&rij);
            }

            local_virial
        }).sum()
    }
}

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

#[cfg(test)]
mod tests {
    pub use super::*;
    use sys::System;
    use energy::GlobalPotential;
    use utils::system_from_xyz;

    const E_BRUTE_FORCE: f64 = -0.09262397663346732;

    pub fn testing_system() -> System {
        let mut system = system_from_xyz("2
        cell: 20.0
        Cl 0.0 0.0 0.0
        Na 1.5 0.0 0.0
        ");
        system.particles_mut().charge[0] = -1.0;
        system.particles_mut().charge[1] = 1.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 mut forces = vec![Vector3D::zero(); system.size()];
        wolf.forces(&system, &mut forces);
        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.particles_mut().position[0][0] += eps;

        let e1 = wolf.energy(&system);
        let mut forces = vec![Vector3D::zero(); system.size()];
        wolf.forces(&system, &mut forces);
        assert_relative_eq!((e - e1) / eps, forces[0][0], 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 cell: 20.0
            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
            ");
            assert!(system.molecules().len() == 2);

            for particle in system.particles_mut() {
                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.particles_mut().position[0] = newpos[0];
            system.particles_mut().position[1] = newpos[1];
            let new_e = check.energy(&system);
            assert_ulps_eq!(cost, new_e - old_e);
        }
    }
}
<|endoftext|>


<commit_before>#![warn(missing_docs)]
#![warn(rust_2018_idioms)]
#![deny(unsafe_code)]

//! A library providing the written english form of a number.
//!
//! # Example
//!
//! ```rust
//! use numeral::Cardinal;
//!
//! let n = 127;
//! println!("{} is written {}", n, n.cardinal());
//! ```

const NUMBER: [&str; 20] = [
    "zero",
    "one",
    "two",
    "three",
    "four",
    "five",
    "six",
    "seven",
    "eight",
    "nine",
    "ten",
    "eleven",
    "twelve",
    "thirteen",
    "fourteen",
    "fifteen",
    "sixteen",
    "seventeen",
    "eighteen",
    "nineteen",
];

#[rustfmt::skip]
const TENS: [&str; 10] = [
    "",
    "",
    "twenty",
    "thirty",
    "forty",
    "fifty",
    "sixty",
    "seventy",
    "eighty",
    "ninety",
];

const MULTIPLIER: [&str; 9] = [
    "",
    "thousand",
    "million",
    "billion",
    "trillion",
    "quadrillion",
    "quintillion",
    "sextillion",
    "septillion",
];

/// Provides the cardinal written form of a number.
pub trait Cardinal {
    /// Returns the cardinal form of a number.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use numeral::Cardinal;
    /// let written_form = 127.cardinal();
    /// assert_eq!(written_form, "one hundred twenty-seven");
    /// ```
    fn cardinal(&self) -> String;
}

macro_rules! impl_numeral_signed {
    ($($numtype:ty),*) => {$(
        impl Cardinal for $numtype {
            fn cardinal(&self) -> String {
                cardinal_int(i64::from(*self).abs() as u64, self.is_negative())
            }
        }
    )*};
}

impl_numeral_signed!(i8, i16, i32);

macro_rules! impl_numeral_unsigned {
    ($($numtype:ty),*) => {$(
        impl Cardinal for $numtype {
            fn cardinal(&self) -> String {
                cardinal_int(u64::from(*self), false)
            }
        }
    )*};
}

impl_numeral_unsigned!(u8, u16, u32, u64);

impl Cardinal for i64 {
    fn cardinal(&self) -> String {
        let n_abs = if *self == i64::MIN { *self as u64 } else { self.abs() as u64 };
        cardinal_int(n_abs, self.is_negative())
    }
}

impl Cardinal for isize {
    fn cardinal(&self) -> String {
        let n_abs = if *self == isize::MIN { *self as usize } else { self.abs() as usize };
        cardinal_int(n_abs as u64, self.is_negative())
    }
}

impl Cardinal for usize {
    fn cardinal(&self) -> String {
        cardinal_int(*self as u64, false)
    }
}

/// Returns the written form of any 64-bit integer
/// as a vector of strings.
fn cardinal_int(n: u64, negative: bool) -> String {
    if n == 0 {
        return String::from(NUMBER[0]);
    }
    let multiple_order = ((n as f32).log10() as u32) / 3;
    let max_len = multiple_order as usize * 8 + 6;
    let mut cardinal = Vec::with_capacity(max_len);
    if negative {
        cardinal.push("minus ");
    }
    compose_cardinal_int(n, multiple_order, &mut cardinal);
    debug_assert!(cardinal.len() <= max_len);
    cardinal.concat()
}

macro_rules! push {
    ($vec:ident, $table:ident[$index:ident]) => {
        debug_assert!(
            ($index as usize) < $table.len(),
            "{} out of {}'s range",
            stringify!($index),
            stringify!($table)
        );
        $vec.push($table[$index as usize]);
    };
}

/// Pushes the strings composing the cardinal form of any unsigned 64-bit number
/// on a vector. Zero is ignored.
fn compose_cardinal_int(mut n: u64, mut multiple_order: u32, cardinal: &mut Vec<&str>) {
    debug_assert_ne!(n, 0, "n == 0 in compose_cardinal_int()");
    debug_assert_eq!(
        multiple_order,
        ((n as f32).log10() as u32) / 3,
        "wrong value for multiple_order in compose_cardinal_int()"
    );

    if multiple_order > 0 {
        let mut multiplier = 10u64.pow(multiple_order * 3);
        let mut multiplicand;
        loop {
            multiplicand = n / multiplier;
            n %= multiplier;
            if multiplicand != 0 {
                push_triplet(multiplicand, cardinal);
                cardinal.push(" ");
                push!(cardinal, MULTIPLIER[multiple_order]);
                if n != 0 {
                    cardinal.push(" ");
                } else {
                    return;
                }
            }
            multiple_order -= 1;
            if multiple_order == 0 {
                break;
            }
            multiplier /= 1000;
        }
    }
    push_triplet(n, cardinal);
}

/// Takes an integer in [1,999] and adds it's written form
/// to a cardinal in construction.
fn push_triplet(n: u64, cardinal: &mut Vec<&str>) {
    debug_assert_ne!(n, 0, "n == 0 in push_triplet()");
    debug_assert!(n < 1000, "n >= 1000 in push_triplet()");

    let hundreds = n / 100;
    let rest = n % 100;
    if hundreds != 0 {
        push!(cardinal, NUMBER[hundreds]);
        if rest == 0 {
            cardinal.push(" hundred");
            return;
        } else {
            cardinal.push(" hundred ");
        }
    }
    push_doublet(rest, cardinal);
}

/// Takes an integer in [1,99] and adds it's written form
/// to a cardinal in construction.
fn push_doublet(n: u64, cardinal: &mut Vec<&str>) {
    debug_assert_ne!(n, 0, "n == 0 in push_doublet()");
    debug_assert!(n < 100, "n >= 100 in push_doublet()");

    if n < 20 {
        push!(cardinal, NUMBER[n]);
    } else {
        let tens = n / 10;
        let ones = n % 10;
        push!(cardinal, TENS[tens]);
        if ones != 0 {
            cardinal.push("-");
            push!(cardinal, NUMBER[ones]);
        }
    }
}
<commit_msg>Fix internal documentation<commit_after>#![warn(missing_docs)]
#![warn(rust_2018_idioms)]
#![deny(unsafe_code)]

//! A library providing the written english form of a number.
//!
//! # Example
//!
//! ```rust
//! use numeral::Cardinal;
//!
//! let n = 127;
//! println!("{} is written {}", n, n.cardinal());
//! ```

const NUMBER: [&str; 20] = [
    "zero",
    "one",
    "two",
    "three",
    "four",
    "five",
    "six",
    "seven",
    "eight",
    "nine",
    "ten",
    "eleven",
    "twelve",
    "thirteen",
    "fourteen",
    "fifteen",
    "sixteen",
    "seventeen",
    "eighteen",
    "nineteen",
];

#[rustfmt::skip]
const TENS: [&str; 10] = [
    "",
    "",
    "twenty",
    "thirty",
    "forty",
    "fifty",
    "sixty",
    "seventy",
    "eighty",
    "ninety",
];

const MULTIPLIER: [&str; 9] = [
    "",
    "thousand",
    "million",
    "billion",
    "trillion",
    "quadrillion",
    "quintillion",
    "sextillion",
    "septillion",
];

/// Provides the cardinal written form of a number.
pub trait Cardinal {
    /// Returns the cardinal form of a number.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use numeral::Cardinal;
    /// let written_form = 127.cardinal();
    /// assert_eq!(written_form, "one hundred twenty-seven");
    /// ```
    fn cardinal(&self) -> String;
}

macro_rules! impl_numeral_signed {
    ($($numtype:ty),*) => {$(
        impl Cardinal for $numtype {
            fn cardinal(&self) -> String {
                cardinal_int(i64::from(*self).abs() as u64, self.is_negative())
            }
        }
    )*};
}

impl_numeral_signed!(i8, i16, i32);

macro_rules! impl_numeral_unsigned {
    ($($numtype:ty),*) => {$(
        impl Cardinal for $numtype {
            fn cardinal(&self) -> String {
                cardinal_int(u64::from(*self), false)
            }
        }
    )*};
}

impl_numeral_unsigned!(u8, u16, u32, u64);

impl Cardinal for i64 {
    fn cardinal(&self) -> String {
        let n_abs = if *self == i64::MIN { *self as u64 } else { self.abs() as u64 };
        cardinal_int(n_abs, self.is_negative())
    }
}

impl Cardinal for isize {
    fn cardinal(&self) -> String {
        let n_abs = if *self == isize::MIN { *self as usize } else { self.abs() as usize };
        cardinal_int(n_abs as u64, self.is_negative())
    }
}

impl Cardinal for usize {
    fn cardinal(&self) -> String {
        cardinal_int(*self as u64, false)
    }
}

/// Returns the written form of any 64-bit unsigned integer as a string.
fn cardinal_int(n: u64, negative: bool) -> String {
    if n == 0 {
        return String::from(NUMBER[0]);
    }
    let multiple_order = ((n as f32).log10() as u32) / 3;
    let max_len = multiple_order as usize * 8 + 6;
    let mut cardinal = Vec::with_capacity(max_len);
    if negative {
        cardinal.push("minus ");
    }
    compose_cardinal_int(n, multiple_order, &mut cardinal);
    debug_assert!(cardinal.len() <= max_len);
    cardinal.concat()
}

macro_rules! push {
    ($vec:ident, $table:ident[$index:ident]) => {
        debug_assert!(
            ($index as usize) < $table.len(),
            "{} out of {}'s range",
            stringify!($index),
            stringify!($table)
        );
        $vec.push($table[$index as usize]);
    };
}

/// Pushes the strings composing the cardinal form of any 64-bit unsigned
/// integer on a `str` stack. Zero is ignored.
fn compose_cardinal_int(mut n: u64, mut multiple_order: u32, cardinal: &mut Vec<&str>) {
    debug_assert_ne!(n, 0, "n == 0 in compose_cardinal_int()");
    debug_assert_eq!(
        multiple_order,
        ((n as f32).log10() as u32) / 3,
        "wrong value for multiple_order in compose_cardinal_int()"
    );

    if multiple_order > 0 {
        let mut multiplier = 10u64.pow(multiple_order * 3);
        let mut multiplicand;
        loop {
            multiplicand = n / multiplier;
            n %= multiplier;
            if multiplicand != 0 {
                push_triplet(multiplicand, cardinal);
                cardinal.push(" ");
                push!(cardinal, MULTIPLIER[multiple_order]);
                if n != 0 {
                    cardinal.push(" ");
                } else {
                    return;
                }
            }
            multiple_order -= 1;
            if multiple_order == 0 {
                break;
            }
            multiplier /= 1000;
        }
    }
    push_triplet(n, cardinal);
}

/// Takes an integer in [1,999] and adds it's written form to a `str` stack.
fn push_triplet(n: u64, cardinal: &mut Vec<&str>) {
    debug_assert_ne!(n, 0, "n == 0 in push_triplet()");
    debug_assert!(n < 1000, "n >= 1000 in push_triplet()");

    let hundreds = n / 100;
    let rest = n % 100;
    if hundreds != 0 {
        push!(cardinal, NUMBER[hundreds]);
        if rest == 0 {
            cardinal.push(" hundred");
            return;
        } else {
            cardinal.push(" hundred ");
        }
    }
    push_doublet(rest, cardinal);
}

/// Takes an integer in [1,99] and adds it's written form to a `str` stack.
fn push_doublet(n: u64, cardinal: &mut Vec<&str>) {
    debug_assert_ne!(n, 0, "n == 0 in push_doublet()");
    debug_assert!(n < 100, "n >= 100 in push_doublet()");

    if n < 20 {
        push!(cardinal, NUMBER[n]);
    } else {
        let tens = n / 10;
        let ones = n % 10;
        push!(cardinal, TENS[tens]);
        if ones != 0 {
            cardinal.push("-");
            push!(cardinal, NUMBER[ones]);
        }
    }
}
<|endoftext|>


<commit_before>#![crate_id = "docopt#0.1.0"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "UNLICENSE"]
#![doc(html_root_url = "http://burntsushi.net/rustdoc/docopt")]

#![allow(dead_code, unused_variable, unused_imports)]
#![allow(visible_private_types)]

//! Docopt for Rust.

#![feature(macro_rules, phase)]

extern crate debug;
extern crate libc;
#[cfg(test)]
#[phase(plugin, link)]
extern crate log;
extern crate regex;
#[phase(plugin)] extern crate regex_macros;

use std::collections::HashMap;
use std::fmt;
use parse::Parser;
use synonym::SynonymMap;

macro_rules! werr(
    ($($arg:tt)*) => (
        match io::stderr().write_str(format!($($arg)*).as_slice()) {
            Ok(_) => (),
            Err(err) => fail!("{}", err),
        }
    )
)

pub type Error = String;

#[deriving(Show)]
pub struct Docopt {
    p: Parser,
    conf: Config,
}

#[deriving(Clone, Show)]
pub struct Config {
    pub options_first: bool,
    pub help: bool,
    pub version: Option<String>,
}

impl Docopt {
    pub fn new(doc: &str, conf: Config) -> Result<Docopt, Error> {
        Ok(Docopt {
            p: try!(Parser::new(doc, conf.options_first)),
            conf: conf,
        })
    }

    pub fn argv(&self, args: &[&str]) -> Result<ValueMap, Error> {
        let argv = try!(self.p.parse_argv(args));
        self.p.matches(&argv)
            .map(|m| Ok(ValueMap { map: m }))
            .unwrap_or(Err("".to_string()))
    }
}

#[deriving(Clone)]
pub struct ValueMap {
    map: SynonymMap<String, Value>,
}

#[deriving(Clone, PartialEq, Show)]
pub enum Value {
    Switch(bool),
    Counted(uint),
    Plain(Option<String>),
    List(Vec<String>),
}

impl ValueMap {
    pub fn get_bool(&self, key: &str) -> bool {
        self.find(&key).map(|v| v.as_bool()).unwrap_or(false)
    }
    pub fn get_count(&self, key: &str) -> uint {
        self.find(&key).map(|v| v.as_count()).unwrap_or(0)
    }
    pub fn get_str<'a>(&'a self, key: &str) -> &'a str {
        self.find(&key).map(|v| v.as_str()).unwrap_or("")
    }
    pub fn get_vec<'a>(&'a self, key: &str) -> Vec<&'a str> {
        self.find(&key).map(|v| v.as_vec()).unwrap_or(vec!())
    }
}

impl Value {
    pub fn as_bool(&self) -> bool {
        match self {
            &Switch(b) => b,
            &Counted(n) => n > 0,
            &Plain(None) => false,
            &Plain(Some(_)) => true,
            &List(ref vs) => !vs.is_empty(),
        }
    }
    pub fn as_count(&self) -> uint {
        match self {
            &Switch(b) => if b { 1 } else { 0 },
            &Counted(n) => n,
            &Plain(None) => 0,
            &Plain(Some(_)) => 1,
            &List(ref vs) => vs.len(),
        }
    }
    pub fn as_str<'a>(&'a self) -> &'a str {
        match self {
            &Switch(_) | &Counted(_) | &Plain(None) | &List(_) => "",
            &Plain(Some(ref s)) => s.as_slice(),
        }
    }
    pub fn as_vec<'a>(&'a self) -> Vec<&'a str> {
        match self {
            &Switch(_) | &Counted(_) | &Plain(None) => vec!(),
            &Plain(Some(ref s)) => vec!(s.as_slice()),
            &List(ref vs) => vs.iter().map(|s| s.as_slice()).collect(),
        }
    }
}

impl Collection for ValueMap {
    fn len(&self) -> uint { self.map.len() }
}

impl<'k> Map<&'k str, Value> for ValueMap {
    fn find<'a>(&'a self, key: & &'k str) -> Option<&'a Value> {
        self.map.find(&key.to_string())
    }
}

impl fmt::Show for ValueMap {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.is_empty() {
            return write!(f, "{{EMPTY}}");
        }

        // This is a little crazy, but we want to group synonyms with
        // their keys and sort them for predictable output.
        let reverse: HashMap<&String, &String> =
            self.map.synonyms().map(|(from, to)| (to, from)).collect();
        let mut keys: Vec<&String> = self.map.keys().collect();
        keys.sort();
        let mut first = true;
        for &k in keys.iter() {
            if !first { try!(write!(f, "\n")); } else { first = false; }
            match reverse.find(&k) {
                None => {
                    try!(write!(f, "{} => {}", k, self.map.get(k)))
                }
                Some(s) => {
                    try!(write!(f, "{}, {} => {}", s, k, self.map.get(k)))
                }
            }
        }
        Ok(())
    }
}

pub fn docopt(doc: &str) -> ValueMap {
    docopt_conf(doc, Config { options_first: false, help: true, version: None })
}

pub fn docopt_conf(doc: &str, conf: Config) -> ValueMap {
    match Docopt::new(doc, conf) {
        Ok(dopt) => convenient_parse_argv(&dopt),
        Err(err) => fail!("{}", err),
    }
}

fn convenient_parse_argv(dopt: &Docopt) -> ValueMap {
    use std::io;
    use std::os;

    let os_argv = os::args();
    let argv: Vec<&str> = os_argv.iter().skip(1).map(|s|s.as_slice()).collect();
    if dopt.conf.help && argv_has_help(argv.as_slice()) {
        werr!("{}\n", dopt.p.full_doc.as_slice().trim());
        exit(1);
    }
    match dopt.conf.version {
        Some(ref v) if argv_has_version(argv.as_slice()) => {
            werr!("{}\n", v);
            exit(0);
        }
        _ => {},
    }
    dopt.argv(argv.as_slice()).unwrap_or_else(|err| {
        if !err.is_empty() {
            werr!("{}\n", err);
        }
        werr!("{}\n", dopt.p.usage.as_slice().trim());
        exit(1);
    })
}

fn argv_has_help(argv: &[&str]) -> bool {
    argv.contains(&"-h") || argv.contains(&"--help")
}

fn argv_has_version(argv: &[&str]) -> bool {
    argv.contains(&"--version")
}

// I've been warned that this is wildly unsafe.
// Unless there's a reasonable alternative, I'm inclined to say that this is
// the price you pay for convenience.
fn exit(code: uint) -> ! {
    unsafe { libc::exit(code as libc::c_int) }
}

mod parse;
mod synonym;
#[cfg(test)]
mod test;

<commit_msg>Temporarily enable debug!.<commit_after>#![crate_id = "docopt#0.1.0"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "UNLICENSE"]
#![doc(html_root_url = "http://burntsushi.net/rustdoc/docopt")]

#![allow(dead_code, unused_variable, unused_imports)]
#![allow(visible_private_types)]

//! Docopt for Rust.

#![feature(macro_rules, phase)]

extern crate debug;
extern crate libc;
// #[cfg(test)]
#[phase(plugin, link)]
extern crate log;
extern crate regex;
#[phase(plugin)] extern crate regex_macros;

use std::collections::HashMap;
use std::fmt;
use parse::Parser;
use synonym::SynonymMap;

macro_rules! werr(
    ($($arg:tt)*) => (
        match io::stderr().write_str(format!($($arg)*).as_slice()) {
            Ok(_) => (),
            Err(err) => fail!("{}", err),
        }
    )
)

pub type Error = String;

#[deriving(Show)]
pub struct Docopt {
    p: Parser,
    conf: Config,
}

#[deriving(Clone, Show)]
pub struct Config {
    pub options_first: bool,
    pub help: bool,
    pub version: Option<String>,
}

impl Docopt {
    pub fn new(doc: &str, conf: Config) -> Result<Docopt, Error> {
        Ok(Docopt {
            p: try!(Parser::new(doc, conf.options_first)),
            conf: conf,
        })
    }

    pub fn argv(&self, args: &[&str]) -> Result<ValueMap, Error> {
        let argv = try!(self.p.parse_argv(args));
        self.p.matches(&argv)
            .map(|m| Ok(ValueMap { map: m }))
            .unwrap_or(Err("".to_string()))
    }
}

#[deriving(Clone)]
pub struct ValueMap {
    map: SynonymMap<String, Value>,
}

#[deriving(Clone, PartialEq, Show)]
pub enum Value {
    Switch(bool),
    Counted(uint),
    Plain(Option<String>),
    List(Vec<String>),
}

impl ValueMap {
    pub fn get_bool(&self, key: &str) -> bool {
        self.find(&key).map(|v| v.as_bool()).unwrap_or(false)
    }
    pub fn get_count(&self, key: &str) -> uint {
        self.find(&key).map(|v| v.as_count()).unwrap_or(0)
    }
    pub fn get_str<'a>(&'a self, key: &str) -> &'a str {
        self.find(&key).map(|v| v.as_str()).unwrap_or("")
    }
    pub fn get_vec<'a>(&'a self, key: &str) -> Vec<&'a str> {
        self.find(&key).map(|v| v.as_vec()).unwrap_or(vec!())
    }
}

impl Value {
    pub fn as_bool(&self) -> bool {
        match self {
            &Switch(b) => b,
            &Counted(n) => n > 0,
            &Plain(None) => false,
            &Plain(Some(_)) => true,
            &List(ref vs) => !vs.is_empty(),
        }
    }
    pub fn as_count(&self) -> uint {
        match self {
            &Switch(b) => if b { 1 } else { 0 },
            &Counted(n) => n,
            &Plain(None) => 0,
            &Plain(Some(_)) => 1,
            &List(ref vs) => vs.len(),
        }
    }
    pub fn as_str<'a>(&'a self) -> &'a str {
        match self {
            &Switch(_) | &Counted(_) | &Plain(None) | &List(_) => "",
            &Plain(Some(ref s)) => s.as_slice(),
        }
    }
    pub fn as_vec<'a>(&'a self) -> Vec<&'a str> {
        match self {
            &Switch(_) | &Counted(_) | &Plain(None) => vec!(),
            &Plain(Some(ref s)) => vec!(s.as_slice()),
            &List(ref vs) => vs.iter().map(|s| s.as_slice()).collect(),
        }
    }
}

impl Collection for ValueMap {
    fn len(&self) -> uint { self.map.len() }
}

impl<'k> Map<&'k str, Value> for ValueMap {
    fn find<'a>(&'a self, key: & &'k str) -> Option<&'a Value> {
        self.map.find(&key.to_string())
    }
}

impl fmt::Show for ValueMap {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.is_empty() {
            return write!(f, "{{EMPTY}}");
        }

        // This is a little crazy, but we want to group synonyms with
        // their keys and sort them for predictable output.
        let reverse: HashMap<&String, &String> =
            self.map.synonyms().map(|(from, to)| (to, from)).collect();
        let mut keys: Vec<&String> = self.map.keys().collect();
        keys.sort();
        let mut first = true;
        for &k in keys.iter() {
            if !first { try!(write!(f, "\n")); } else { first = false; }
            match reverse.find(&k) {
                None => {
                    try!(write!(f, "{} => {}", k, self.map.get(k)))
                }
                Some(s) => {
                    try!(write!(f, "{}, {} => {}", s, k, self.map.get(k)))
                }
            }
        }
        Ok(())
    }
}

pub fn docopt(doc: &str) -> ValueMap {
    docopt_conf(doc, Config { options_first: false, help: true, version: None })
}

pub fn docopt_conf(doc: &str, conf: Config) -> ValueMap {
    match Docopt::new(doc, conf) {
        Ok(dopt) => convenient_parse_argv(&dopt),
        Err(err) => fail!("{}", err),
    }
}

fn convenient_parse_argv(dopt: &Docopt) -> ValueMap {
    use std::io;
    use std::os;

    let os_argv = os::args();
    let argv: Vec<&str> = os_argv.iter().skip(1).map(|s|s.as_slice()).collect();
    if dopt.conf.help && argv_has_help(argv.as_slice()) {
        werr!("{}\n", dopt.p.full_doc.as_slice().trim());
        exit(1);
    }
    match dopt.conf.version {
        Some(ref v) if argv_has_version(argv.as_slice()) => {
            werr!("{}\n", v);
            exit(0);
        }
        _ => {},
    }
    dopt.argv(argv.as_slice()).unwrap_or_else(|err| {
        if !err.is_empty() {
            werr!("{}\n", err);
        }
        werr!("{}\n", dopt.p.usage.as_slice().trim());
        exit(1);
    })
}

fn argv_has_help(argv: &[&str]) -> bool {
    argv.contains(&"-h") || argv.contains(&"--help")
}

fn argv_has_version(argv: &[&str]) -> bool {
    argv.contains(&"--version")
}

// I've been warned that this is wildly unsafe.
// Unless there's a reasonable alternative, I'm inclined to say that this is
// the price you pay for convenience.
fn exit(code: uint) -> ! {
    unsafe { libc::exit(code as libc::c_int) }
}

mod parse;
mod synonym;
#[cfg(test)]
mod test;

<|endoftext|>


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

use autocxx_engine::IncludeCpp;
use proc_macro::TokenStream;
use proc_macro_error::{proc_macro_error, abort_call_site};
use syn::parse_macro_input;

/// Include some C++ headers in your Rust project.
///
/// This macro allows you to include one or more C++ headers within
/// your Rust code, and call their functions fairly naturally.
///
/// # Examples
///
/// ```text
/// #include <cstdint>
///
/// uint32_t do_math(uint32_t a);
/// ```
///
/// ```
/// # use autocxx::include_cxx;
/// include_cxx!(
/// #   ParseOnly,
///     Header("input.h"),
///     Allow("do_math"),
/// );
///
/// # mod ffi { pub fn do_math(a: u32) -> u32 { a+3 } }
/// # fn main() {
/// ffi::do_math(3);
/// # }
/// ```
#[proc_macro_error]
#[proc_macro]
pub fn include_cxx(input: TokenStream) -> TokenStream {
    let include_cpp = parse_macro_input!(input as IncludeCpp);
    match include_cpp.generate_rs() {
        Ok(ts) => TokenStream::from(ts),
        Err(e) => abort_call_site!(format!("{:?}", e))
    }
}
<commit_msg>More rustdoc.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use autocxx_engine::IncludeCpp;
use proc_macro::TokenStream;
use proc_macro_error::{proc_macro_error, abort_call_site};
use syn::parse_macro_input;

/// Include some C++ headers in your Rust project.
///
/// This macro allows you to include one or more C++ headers within
/// your Rust code, and call their functions fairly naturally.
///
/// # Examples
///
/// C++ header (`input.h`):
/// ```cpp
/// #include <cstdint>
///
/// uint32_t do_math(uint32_t a);
/// ```
///
/// Rust code:
/// ```
/// # use autocxx::include_cxx;
/// include_cxx!(
/// #   ParseOnly,
///     Header("input.h"),
///     Allow("do_math"),
/// );
///
/// # mod ffi { pub fn do_math(a: u32) -> u32 { a+3 } }
/// # fn main() {
/// ffi::do_math(3);
/// # }
/// ```
///
/// # Configuring the build
///
/// To build this, you'll need to:
/// * Educate the procedural macro about where to find the C++ headers. Set the
///   `AUTOCXX_INC` environment variable to a list of directories to search.
/// * Build the C++ side of the bindings. You'll need to use the `autocxx-gen`
///   crate (or similar) to process the same .rs code into C++ header and
///   implementation files.
///
/// # Syntax
///
/// Within the brackets of the `include_cpp!(...)` macro, you should provide
/// a list of the following:
///
/// * *Header(filename)*: a header filename to parse and include
/// * *Allow(type or function name)*: a type or function name whose declaration
///   should be made available to C++.
#[proc_macro_error]
#[proc_macro]
pub fn include_cxx(input: TokenStream) -> TokenStream {
    let include_cpp = parse_macro_input!(input as IncludeCpp);
    match include_cpp.generate_rs() {
        Ok(ts) => TokenStream::from(ts),
        Err(e) => abort_call_site!(format!("{:?}", e))
    }
}
<|endoftext|>


<commit_before>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate take_mut;

use std::io;
use std::error::Error;
use std::marker::PhantomData;

#[derive(Debug)]
pub enum DecodingError {
    Corrupt(String),
    IoError(io::Error),
}

fn decode<O: serde::de::DeserializeOwned, R: io::Read+io::Seek>(reader: &mut R, offset: u64) -> Result<O, DecodingError> {
    reader.seek(io::SeekFrom::Start(offset)).map_err(|x| DecodingError::IoError(x))?;
    bincode::deserialize_from(    reader, bincode::Infinite)
    .map_err(|x| {
        match *x {
            bincode::ErrorKind::IoError(y) => DecodingError::IoError(y),
            _ => DecodingError::Corrupt(x.description().to_string()),
        }
    })
}

#[derive(Debug)]
pub enum EncodingError {
    Unknown(String),
    IoError(io::Error),
}

fn encode<O: serde::Serialize, W: io::Write+io::Seek>(writer: &mut W, obj: &O) -> Result<u64, EncodingError> {
    let offset = writer.seek(io::SeekFrom::End(0)).map_err(|x| EncodingError::IoError(x))?;
    bincode::serialize_into(writer, obj, bincode::Infinite)
    .map_err(|x| {
        match *x {
            bincode::ErrorKind::IoError(y) => EncodingError::IoError(y),
            _ => EncodingError::Unknown(x.description().to_string()),
        }
    }).map(|_| offset)
}

#[derive(Serialize, Deserialize, Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
enum NodeType {
    Root,
    Internal,
    Leaf
}

enum NodeRef<K> {
    Unloaded(u64),
    Loaded(Box<Node<K>>),
    Modified(Box<Node<K>>),
}

// An on-disk representation, for space saving.
#[derive(Serialize, Deserialize)]
struct DiskNode<K> {
    node_type: NodeType,
    children: Vec<(K, u64)>,
    after_last: u64,
}

struct Node<K> {
    node_type: NodeType,
    children: Vec<(K, NodeRef<K>)>,
    after_last: NodeRef<K>,
}

impl<K> From<DiskNode<K>> for Node<K> {
    fn from(obj: DiskNode<K>) -> Node<K> {
        Node {
            node_type: obj.node_type,
            children: obj.children.into_iter().map(|x| (x.0, NodeRef::Unloaded(x.1))).collect(),
            after_last: NodeRef::Unloaded(obj.after_last),
        }
    }
}

impl<K: serde::de::DeserializeOwned> DiskNode<K> {
    fn load<R: io::Read+io::Seek>(reader: &mut R, offset: u64) -> Result<DiskNode<K>, DecodingError> {
        decode(reader, offset)
    }
}

impl<K: serde::de::DeserializeOwned> NodeRef<K> {

    fn load<R: io::Read+io::Seek>(reader: &mut R, offset: u64) -> Result<Node<K>, DecodingError> {
        Ok(DiskNode::<K>::load(reader, offset)?.into())
    }

    // Upgrade through the variants, optionally all the way to mutable.
    fn upgrade<R: io::Read+io::Seek>(&mut self, reader: &mut R, modification: bool) -> Result<(), DecodingError> {
        let new: Option<Box<Node<K>>> = match *self {
            NodeRef::Unloaded(offset) => Some(Box::new(NodeRef::load(reader, offset)?)),
            _ => None,
        };
        // If we have a new one, construct the appropriate variant directly.
        if let Some(b)  = new {
            if modification {
                *self = NodeRef::Modified(b);
            } else {
                *self = NodeRef::Loaded(b);
            }
            return Ok(());
        }
        // If we get here, it's either Loaded or Modified, with a possible need for an upgrade.
        if modification {
            take_mut::take(self, |x| match x {
                NodeRef::Loaded(b) | NodeRef::Modified(b) => NodeRef::Modified(b),
                _ => panic!("The node should be loaded."),
            });
        }
        Ok(())
    }

    fn examine<R: io::Read+io::Seek>(&mut self, reader: &mut R) -> Result<&mut Node<K>, DecodingError> {
        self.upgrade(reader, false)?;
        Ok(match *self {
            NodeRef::Loaded(ref mut n) => n,
            NodeRef::Modified(ref mut n) => n,
            _ => panic!("Nodes should be loaded."),
        })
    }

    fn modify<R: io::Read+io::Seek>(&mut self, reader: &mut R) -> Result<&mut Node<K>, DecodingError> {
        self.upgrade(reader, true);
        Ok(match *self {
            NodeRef::Modified(ref mut n) => n,
            _ => panic!("Nodes should be modified."),
        })
    }
}

impl<K: serde::de::DeserializeOwned+Eq+Ord> Node<K> {
    fn find_offset_for<R: io::Read+io::Seek>(&mut self, reader: &mut R, key: &K) -> Result<Option<u64>, DecodingError> {
        // If we're the root and there are no children, this is the empty tree.
        if self.node_type == NodeType::Root && self.children.len() == 0 { return Ok(None) }
        let index = self.children.binary_search_by_key(&key, |x| &x.0);
        let mut reference;
        match index {
            Ok(ind) if self.node_type == NodeType::Leaf => {
                let r = &self.children[ind].1;
                match *r {
                    NodeRef::Unloaded(offset) => return Ok(Some(offset)),
                    _ => panic!("Tree contains leaf inside leaf."),
                }
            }
            // The right subtree is >, the left subtree is <=.
            // The vector stores the offset of the left subtree.
            Ok(ind) => {
                reference = &mut self.children[ind].1;
            }
            Err(ind) => {
                // Recall that empty nodes are not possible.
                if ind < self.children.len() {
                    reference = &mut self.children[ind].1;
                } else {
                    reference = &mut self.after_last;
                }
            }
        }
        reference.examine(reader)?.find_offset_for(reader, key)
    }
}

struct BPTree<'a, R: 'a, K, V> {
    root_reference: NodeRef<K>,
    backing_io: &'a mut R,
    _phantom: PhantomData<V>
}

impl<'a, R: io::Read+io::Seek, K: serde::de::DeserializeOwned+Eq+Ord, V> BPTree<'a, R, K, V> {
    pub fn contains(&mut self, key: &K) -> Result<bool, DecodingError> {
        Ok(self.offset_for(key)?.is_some())
    }

    pub fn offset_for(&mut self, key: &K) -> Result<Option<u64>, DecodingError> {
        self.root_reference.examine(self.backing_io)?.find_offset_for(self.backing_io, key)
    }
}<commit_msg>Reimplement searching in terms of a more fundamental step_toward primitive.<commit_after>#![allow(dead_code)]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate take_mut;

use std::io;
use std::error::Error;
use std::marker::PhantomData;

#[derive(Debug)]
pub enum DecodingError {
    Corrupt(String),
    IoError(io::Error),
}

fn decode<O: serde::de::DeserializeOwned, R: io::Read+io::Seek>(reader: &mut R, offset: u64) -> Result<O, DecodingError> {
    reader.seek(io::SeekFrom::Start(offset)).map_err(|x| DecodingError::IoError(x))?;
    bincode::deserialize_from(    reader, bincode::Infinite)
    .map_err(|x| {
        match *x {
            bincode::ErrorKind::IoError(y) => DecodingError::IoError(y),
            _ => DecodingError::Corrupt(x.description().to_string()),
        }
    })
}

#[derive(Debug)]
pub enum EncodingError {
    Unknown(String),
    IoError(io::Error),
}

fn encode<O: serde::Serialize, W: io::Write+io::Seek>(writer: &mut W, obj: &O) -> Result<u64, EncodingError> {
    let offset = writer.seek(io::SeekFrom::End(0)).map_err(|x| EncodingError::IoError(x))?;
    bincode::serialize_into(writer, obj, bincode::Infinite)
    .map_err(|x| {
        match *x {
            bincode::ErrorKind::IoError(y) => EncodingError::IoError(y),
            _ => EncodingError::Unknown(x.description().to_string()),
        }
    }).map(|_| offset)
}

#[derive(Serialize, Deserialize, Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
enum NodeType {
    Root,
    Internal,
    Leaf
}

enum NodeRef<K> {
    Unloaded(u64),
    Loaded(Box<Node<K>>),
    Modified(Box<Node<K>>),
}

// An on-disk representation, for space saving.
#[derive(Serialize, Deserialize)]
struct DiskNode<K> {
    node_type: NodeType,
    children: Vec<(K, u64)>,
    after_last: u64,
}

struct Node<K> {
    node_type: NodeType,
    children: Vec<(K, NodeRef<K>)>,
    after_last: NodeRef<K>,
}

impl<K> From<DiskNode<K>> for Node<K> {
    fn from(obj: DiskNode<K>) -> Node<K> {
        Node {
            node_type: obj.node_type,
            children: obj.children.into_iter().map(|x| (x.0, NodeRef::Unloaded(x.1))).collect(),
            after_last: NodeRef::Unloaded(obj.after_last),
        }
    }
}

impl<K: serde::de::DeserializeOwned> DiskNode<K> {
    fn load<R: io::Read+io::Seek>(reader: &mut R, offset: u64) -> Result<DiskNode<K>, DecodingError> {
        decode(reader, offset)
    }
}

impl<K: serde::de::DeserializeOwned> NodeRef<K> {
    fn load<R: io::Read+io::Seek>(reader: &mut R, offset: u64) -> Result<Node<K>, DecodingError> {
        Ok(DiskNode::<K>::load(reader, offset)?.into())
    }

    // Upgrade through the variants, optionally all the way to mutable.
    fn upgrade<R: io::Read+io::Seek>(&mut self, reader: &mut R, modification: bool) -> Result<(), DecodingError> {
        let new: Option<Box<Node<K>>> = match *self {
            NodeRef::Unloaded(offset) => Some(Box::new(NodeRef::load(reader, offset)?)),
            _ => None,
        };
        // If we have a new one, construct the appropriate variant directly.
        if let Some(b)  = new {
            if modification {
                *self = NodeRef::Modified(b);
            } else {
                *self = NodeRef::Loaded(b);
            }
            return Ok(());
        }
        // If we get here, it's either Loaded or Modified, with a possible need for an upgrade.
        if modification {
            take_mut::take(self, |x| match x {
                NodeRef::Loaded(b) | NodeRef::Modified(b) => NodeRef::Modified(b),
                _ => panic!("The node should be loaded."),
            });
        }
        Ok(())
    }

    fn examine<R: io::Read+io::Seek>(&mut self, reader: &mut R) -> Result<&mut Node<K>, DecodingError> {
        self.upgrade(reader, false)?;
        Ok(match *self {
            NodeRef::Loaded(ref mut n) => n,
            NodeRef::Modified(ref mut n) => n,
            _ => panic!("Nodes should be loaded."),
        })
    }

    fn modify<R: io::Read+io::Seek>(&mut self, reader: &mut R) -> Result<&mut Node<K>, DecodingError> {
        self.upgrade(reader, true)?;
        Ok(match *self {
            NodeRef::Modified(ref mut n) => n,
            _ => panic!("Nodes should be modified."),
        })
    }
}

impl<K: serde::de::DeserializeOwned+Eq+Ord> Node<K> {
    fn find_offset_for<R: io::Read+io::Seek>(&mut self, reader: &mut R, key: &K) -> Result<Option<u64>, DecodingError> {
        // If we're the root and there are no children, this is the empty tree.
        if self.node_type == NodeType::Root && self.children.len() == 0 { Ok(None) }
        else if self.node_type == NodeType::Leaf {
            match self.children.binary_search_by_key(&key, |x| &x.0) {
                Ok(ind) => Ok(Some(match self.children[ind].1 {
                    NodeRef::Unloaded(offset) => offset,
                    _ => panic!("This is supposed to be a leaf, but the child is somehow loaded.")
                })),
                Err(_) => Ok(None),
            }
        }
        else {
            self.step_toward(key).examine(reader)?.find_offset_for(reader, key)
        }
    }

    fn step_toward(&mut self, key: &K) -> &mut NodeRef<K> {
        assert!(self.node_type != NodeType::Leaf);
        let ind = self.children.binary_search_by_key(&key, |x| &x.0);
        match ind {
            // Each subtree <= the key.
            Ok(index) => &mut self.children[index].1,
            Err(index) =>
                if index == self.children.len() { &mut self.after_last } else { &mut self.children[index+1].1 },
        }
    }
}

struct BPTree<'a, R: 'a, K, V> {
    root_reference: NodeRef<K>,
    backing_io: &'a mut R,
    _phantom: PhantomData<V>
}

impl<'a, R: io::Read+io::Seek, K: serde::de::DeserializeOwned+Eq+Ord, V> BPTree<'a, R, K, V> {
    pub fn contains(&mut self, key: &K) -> Result<bool, DecodingError> {
        Ok(self.offset_for(key)?.is_some())
    }

    pub fn offset_for(&mut self, key: &K) -> Result<Option<u64>, DecodingError> {
        self.root_reference.examine(self.backing_io)?.find_offset_for(self.backing_io, key)
    }
}<|endoftext|>


<commit_before>//! gcm
//! ===
//!
//! # Usage:
//!
//! Add this to `Cargo.toml`:
//!
//! ```ignore
//! [dependencies]
//! gcm = "0.1.4"
//! ```
//!
//! then add this to your crate root:
//!
//! ```ignore
//! extern crate gcm;
//! ```
//!
//! # Examples:
//!
//! Here is an example to send out a GCM Message with some custom data:
//!
//! ```no_run
//! use gcm::Message;
//! use std::collections::HashMap;
//!
//! let mut map = HashMap::new();
//! map.insert("message", "Howdy!");
//!
//! let result = Message::new("<registration id>")
//!     .data(map)
//!     .send("<GCM API Key>");
//! ```
//!
//! To send a message using GCM Notifications, we first build the notification:
//!
//! ```rust
//! use gcm::{Message, NotificationBuilder};
//!
//! let notification = NotificationBuilder::new("Hey!")
//!     .body("Do you want to catch up later?")
//!     .finalize();
//! ```
//! And then set it in the message, before sending it:
//!
//! ```no_run
//! # use gcm::{Message, NotificationBuilder};
//! # let notification = NotificationBuilder::new("Hey!")
//! #     .body("Do you want to catch up later?")
//! #     .finalize();
//! let result = Message::new("<registration id>")
//!     .notification(notification)
//!     .send("<GCM API Key>");
//! ```
//! You can now handle the result accordingly:
//!
//! ```no_run
//! # use gcm::{Message, NotificationBuilder};
//! # let notification = NotificationBuilder::new("Hey!")
//! #     .body("Do you want to catch up later?")
//! #     .finalize();
//! # let result = Message::new("<registration id>")
//! #     .notification(notification)
//! #     .send("<GCM API Key>");
//! match result {
//!   Ok(response) => println!("message_id: {:?}", response.message_id),
//!   Err(error) => println!("Error: {:?}", error),
//! }
//! ```

mod message;
pub use message::*;
mod notification;
pub use notification::*;

pub use message::response::GcmError as Error;

extern crate rustc_serialize;
extern crate curl;
<commit_msg>Move extern crate declarations to the top<commit_after>//! gcm
//! ===
//!
//! # Usage:
//!
//! Add this to `Cargo.toml`:
//!
//! ```ignore
//! [dependencies]
//! gcm = "0.1.4"
//! ```
//!
//! then add this to your crate root:
//!
//! ```ignore
//! extern crate gcm;
//! ```
//!
//! # Examples:
//!
//! Here is an example to send out a GCM Message with some custom data:
//!
//! ```no_run
//! use gcm::Message;
//! use std::collections::HashMap;
//!
//! let mut map = HashMap::new();
//! map.insert("message", "Howdy!");
//!
//! let result = Message::new("<registration id>")
//!     .data(map)
//!     .send("<GCM API Key>");
//! ```
//!
//! To send a message using GCM Notifications, we first build the notification:
//!
//! ```rust
//! use gcm::{Message, NotificationBuilder};
//!
//! let notification = NotificationBuilder::new("Hey!")
//!     .body("Do you want to catch up later?")
//!     .finalize();
//! ```
//! And then set it in the message, before sending it:
//!
//! ```no_run
//! # use gcm::{Message, NotificationBuilder};
//! # let notification = NotificationBuilder::new("Hey!")
//! #     .body("Do you want to catch up later?")
//! #     .finalize();
//! let result = Message::new("<registration id>")
//!     .notification(notification)
//!     .send("<GCM API Key>");
//! ```
//! You can now handle the result accordingly:
//!
//! ```no_run
//! # use gcm::{Message, NotificationBuilder};
//! # let notification = NotificationBuilder::new("Hey!")
//! #     .body("Do you want to catch up later?")
//! #     .finalize();
//! # let result = Message::new("<registration id>")
//! #     .notification(notification)
//! #     .send("<GCM API Key>");
//! match result {
//!   Ok(response) => println!("message_id: {:?}", response.message_id),
//!   Err(error) => println!("Error: {:?}", error),
//! }
//! ```

extern crate rustc_serialize;
extern crate curl;

mod message;
pub use message::*;
mod notification;
pub use notification::*;

pub use message::response::GcmError as Error;

<|endoftext|>


<commit_before>#![allow(clippy::missing_safety_doc)] // FIXME

//! `rust-numpy` provides Rust interfaces for [NumPy C APIs](https://numpy.org/doc/stable/reference/c-api),
//! especially for [ndarray](https://numpy.org/doc/stable/reference/arrays.ndarray.html) class.
//!
//! It uses [pyo3](https://github.com/PyO3/pyo3) for rust bindings to cpython, and uses
//! [ndarray](https://github.com/bluss/ndarray) for rust side matrix library.
//!
//! For numpy dependency, it calls `import numpy.core` internally. So you just need numpy
//! installed by `pip install numpy` or other ways in your python environment.
//! You can use both system environment and `virtualenv`.
//!
//! This library loads numpy module automatically. So if numpy is not installed, it simply panics,
//! instead of returing a result.
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate ndarray;
//! use numpy::{ToPyArray, PyArray};
//! fn main() {
//!     pyo3::Python::with_gil(|py| {
//!         let py_array = array![[1i64, 2], [3, 4]].to_pyarray(py);
//!         assert_eq!(
//!             py_array.readonly().as_array(),
//!             array![[1i64, 2], [3, 4]]
//!         );
//!     })
//! }
//! ```

#[macro_use]
extern crate cfg_if;
#[macro_use]
extern crate pyo3;

pub mod array;
pub mod convert;
mod dtype;
mod error;
pub mod npyffi;
pub mod npyiter;
mod readonly;
mod slice_box;
mod sum_products;

pub use crate::array::{
    get_array_module, PyArray, PyArray0, PyArray1, PyArray2, PyArray3, PyArray4, PyArray5,
    PyArray6, PyArrayDyn,
};
pub use crate::convert::{IntoPyArray, NpyIndex, ToNpyDims, ToPyArray};
pub use crate::dtype::{c32, c64, DataType, Element, PyArrayDescr};
pub use crate::error::{FromVecError, NotContiguousError, ShapeError};
pub use crate::npyffi::{PY_ARRAY_API, PY_UFUNC_API};
pub use crate::npyiter::{
    IterMode, NpyIterFlag, NpyMultiIter, NpyMultiIterBuilder, NpySingleIter, NpySingleIterBuilder,
};
pub use crate::readonly::{
    PyReadonlyArray, PyReadonlyArray1, PyReadonlyArray2, PyReadonlyArray3, PyReadonlyArray4,
    PyReadonlyArray5, PyReadonlyArray6, PyReadonlyArrayDyn,
};
pub use crate::sum_products::{dot, einsum_impl, inner};
pub use ndarray::{array, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn};

/// Test readme
#[doc(hidden)]
pub mod doc_test {
    macro_rules! doc_comment {
        ($x: expr, $modname: ident) => {
            #[doc = $x]
            mod $modname {}
        };
    }
    doc_comment!(include_str!("../README.md"), readme);
}

/// Create a [PyArray](./array/struct.PyArray.html) with one, two or three dimensions.
/// This macro is backed by
/// [`ndarray::array`](https://docs.rs/ndarray/latest/ndarray/macro.array.html).
///
/// # Example
/// ```
/// pyo3::Python::with_gil(|py| {
///     let array = numpy::pyarray![py, [1, 2], [3, 4]];
///     assert_eq!(
///         array.readonly().as_array(),
///         ndarray::array![[1, 2], [3, 4]]
///     );
/// });
#[macro_export]
macro_rules! pyarray {
    ($py: ident, $([$([$($x:expr),* $(,)*]),+ $(,)*]),+ $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$([$([$($x,)*],)*],)*], $py)
    }};
    ($py: ident, $([$($x:expr),* $(,)*]),+ $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$([$($x,)*],)*], $py)
    }};
    ($py: ident, $($x:expr),* $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$($x,)*], $py)
    }};
}
<commit_msg>Re-export ndarray to avoid having to specify the correct version in downstream crates.<commit_after>#![allow(clippy::missing_safety_doc)] // FIXME

//! `rust-numpy` provides Rust interfaces for [NumPy C APIs](https://numpy.org/doc/stable/reference/c-api),
//! especially for [ndarray](https://numpy.org/doc/stable/reference/arrays.ndarray.html) class.
//!
//! It uses [pyo3](https://github.com/PyO3/pyo3) for rust bindings to cpython, and uses
//! [ndarray](https://github.com/bluss/ndarray) for rust side matrix library.
//!
//! For numpy dependency, it calls `import numpy.core` internally. So you just need numpy
//! installed by `pip install numpy` or other ways in your python environment.
//! You can use both system environment and `virtualenv`.
//!
//! This library loads numpy module automatically. So if numpy is not installed, it simply panics,
//! instead of returing a result.
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate ndarray;
//! use numpy::{ToPyArray, PyArray};
//! fn main() {
//!     pyo3::Python::with_gil(|py| {
//!         let py_array = array![[1i64, 2], [3, 4]].to_pyarray(py);
//!         assert_eq!(
//!             py_array.readonly().as_array(),
//!             array![[1i64, 2], [3, 4]]
//!         );
//!     })
//! }
//! ```

#[macro_use]
extern crate cfg_if;
#[macro_use]
extern crate pyo3;

pub mod array;
pub mod convert;
mod dtype;
mod error;
pub mod npyffi;
pub mod npyiter;
mod readonly;
mod slice_box;
mod sum_products;

pub use ndarray;

pub use crate::array::{
    get_array_module, PyArray, PyArray0, PyArray1, PyArray2, PyArray3, PyArray4, PyArray5,
    PyArray6, PyArrayDyn,
};
pub use crate::convert::{IntoPyArray, NpyIndex, ToNpyDims, ToPyArray};
pub use crate::dtype::{c32, c64, DataType, Element, PyArrayDescr};
pub use crate::error::{FromVecError, NotContiguousError, ShapeError};
pub use crate::npyffi::{PY_ARRAY_API, PY_UFUNC_API};
pub use crate::npyiter::{
    IterMode, NpyIterFlag, NpyMultiIter, NpyMultiIterBuilder, NpySingleIter, NpySingleIterBuilder,
};
pub use crate::readonly::{
    PyReadonlyArray, PyReadonlyArray1, PyReadonlyArray2, PyReadonlyArray3, PyReadonlyArray4,
    PyReadonlyArray5, PyReadonlyArray6, PyReadonlyArrayDyn,
};
pub use crate::sum_products::{dot, einsum_impl, inner};
pub use ndarray::{array, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn};

/// Test readme
#[doc(hidden)]
pub mod doc_test {
    macro_rules! doc_comment {
        ($x: expr, $modname: ident) => {
            #[doc = $x]
            mod $modname {}
        };
    }
    doc_comment!(include_str!("../README.md"), readme);
}

/// Create a [PyArray](./array/struct.PyArray.html) with one, two or three dimensions.
/// This macro is backed by
/// [`ndarray::array`](https://docs.rs/ndarray/latest/ndarray/macro.array.html).
///
/// # Example
/// ```
/// pyo3::Python::with_gil(|py| {
///     let array = numpy::pyarray![py, [1, 2], [3, 4]];
///     assert_eq!(
///         array.readonly().as_array(),
///         ndarray::array![[1, 2], [3, 4]]
///     );
/// });
#[macro_export]
macro_rules! pyarray {
    ($py: ident, $([$([$($x:expr),* $(,)*]),+ $(,)*]),+ $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$([$([$($x,)*],)*],)*], $py)
    }};
    ($py: ident, $([$($x:expr),* $(,)*]),+ $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$([$($x,)*],)*], $py)
    }};
    ($py: ident, $($x:expr),* $(,)*) => {{
        $crate::IntoPyArray::into_pyarray($crate::array![$($x,)*], $py)
    }};
}
<|endoftext|>


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

use specs::{Entities, Read, ReadStorage, System, WriteStorage};

use crate::animation::ImageType;
use crate::combat::components::collision::{CollisionBox, Points};
use crate::combat::components::{Action, Body, Draw, Facing, Position, State, Weapon};
use crate::files::collide::CollisionBoxes;
use crate::game::EncounterTextures;
use crate::objects::TextureAtlas;
use crate::rect::{Point, Rect};

pub struct UpdateBoundingBoxes;

impl<'a> System<'a> for UpdateBoundingBoxes {
    type SystemData = (
        Read<'a, CollisionBoxes>,
        Read<'a, EncounterTextures>,
        ReadStorage<'a, Draw>,
        ReadStorage<'a, Position>,
        ReadStorage<'a, State>,
        WriteStorage<'a, Body>,
        WriteStorage<'a, Weapon>,
    );

    fn run(
        &mut self,
        (
            collision_boxes,
            encounter_textures,
            draw,
            position,
            state,
            mut body,
            mut weapon,
        ): Self::SystemData,
    ) {
        use specs::Join;
        let collision_data = &collision_boxes.data;
        let textures = &encounter_textures.data;
        for (draw, position, state, body, weapon) in
            (&draw, &position, &state, &mut body, &mut weapon).join()
        {
            let mut weapon_boxes: Vec<Points> = vec![];
            let mut body_boxes: Vec<CollisionBox> = vec![];
            for image in draw.frame.images.iter() {
                match image.image_type {
                    ImageType::Collider => {
                        if let Some(collision_points) = collision_data.get(&image.sheet) {
                            if let Some(points) = &collision_points.points[image.image] {
                                let mut image_global_x: i32 =
                                    position.x as i32 + image.x * state.direction as i32;
                                let image_global_y: i32 = position.y as i32 + image.y;
                                image_global_x = match state.direction {
                                    Facing::Left => image_global_x - points.max_x as i32,
                                    Facing::Right => image_global_x,
                                };
                                weapon_boxes.push(Points {
                                    bounding: Rect {
                                        // x: image.x * state.direction as i32,
                                        // y: image.y,
                                        x: image_global_x,
                                        y: image_global_y,
                                        w: points.max_x,
                                        h: points.max_y,
                                    },
                                    points: points
                                        .data
                                        .iter()
                                        .map(|p| Point {
                                            x: image_global_x + p.x * state.direction as i32,
                                            y: image_global_y + p.y,
                                            // x: p.x * state.direction as i32,
                                            // y: p.y,
                                        })
                                        .collect(),
                                })
                            }
                        }
                    }
                    ImageType::Collidee => {
                        if let Some(texture) = textures.get(&image.sheet) {
                            let rect = &texture.rects[image.image];
                            let mut image_global_x: i32 =
                                position.x as i32 + image.x * state.direction as i32;
                            image_global_x = match state.direction {
                                Facing::Left => image_global_x - rect.w as i32,
                                Facing::Right => image_global_x,
                            };
                            body_boxes.push(CollisionBox {
                                rect: Rect {
                                    x: image_global_x,
                                    y: position.y as i32 + image.y,
                                    w: rect.w,
                                    h: rect.h,
                                },
                                sheet: image.sheet.clone(),
                                image_num: image.image as u32,
                            })
                        }
                    }
                    _ => (),
                }
            }

            if weapon_boxes.is_empty() {
                weapon.collision_points = None;
            } else {
                weapon.collision_points = Some(weapon_boxes);
            }

            if body_boxes.is_empty() {
                body.collision_boxes = None;
            } else {
                body.collision_boxes = Some(body_boxes);
            }
        }
    }
}

pub struct CheckCollisions;

impl<'a> System<'a> for CheckCollisions {
    type SystemData = (
        Read<'a, EncounterTextures>,
        ReadStorage<'a, State>,
        ReadStorage<'a, Position>,
        ReadStorage<'a, Body>,
        ReadStorage<'a, Weapon>,
        Entities<'a>,
    );

    fn run(
        &mut self,
        (encounter_textures, state, position, bodies, weapons, entities): Self::SystemData,
    ) {
        use specs::Join;
        let textures = &encounter_textures.data;
        for (state, attacker_position, weapon, attacker) in
            (&state, &position, &weapons, &*entities)
                .join()
                .filter(|(s, ..)| s.action.is_attack())
        {
            for (defender, body, defender_position) in (&*entities, &bodies, &position)
                .join()
                .filter(|(defender, ..)| attacker.id() != defender.id())
            {
                let hit = check_collision(&textures, weapon, body);
                if hit {
                    println!("hit");
                }
            }
        }
    }
}

fn check_collision(textures: &HashMap<String, TextureAtlas>, weapon: &Weapon, body: &Body) -> bool {
    for weapon_part in weapon.collision_points.iter().flat_map(|v| v) {
        // each attacking image in the attacker
        for body_part in body
            .collision_boxes
            .iter() // Option.iter()
            .flat_map(|v| v)
            .filter(|b| weapon_part.bounding.intersects(&b.rect))
        {
            // check that against each defending image in the defender
            for point in weapon_part
                .points
                .iter()
                .filter(|p| body_part.rect.contains_point(p))
            {
                // check the points collide and the pixel in the image is a part of the target
                let hit_x = point.x - body_part.rect.x;
                let hit_y = point.y - body_part.rect.y;
                let texture = textures
                    .get(&body_part.sheet)
                    .expect("Encounter hasn't loaded correct textures to as world resource");
                let collision_lookup = hit_x as usize * texture.image.width + hit_y as usize;
                let pixel = texture.image.pixels[collision_lookup];
                if pixel > 0 {
                    return true;
                }
            }
        }
    }
    false
}
<commit_msg>only check collisions for entities within 10 pixels of another.<commit_after>use std::collections::HashMap;

use specs::{Entities, Read, ReadStorage, System, WriteStorage};

use crate::animation::ImageType;
use crate::combat::components::collision::{CollisionBox, Points};
use crate::combat::components::{Action, Body, Draw, Facing, Position, State, Weapon};
use crate::files::collide::CollisionBoxes;
use crate::game::EncounterTextures;
use crate::objects::TextureAtlas;
use crate::rect::{Point, Rect};

pub struct UpdateBoundingBoxes;

impl<'a> System<'a> for UpdateBoundingBoxes {
    type SystemData = (
        Read<'a, CollisionBoxes>,
        Read<'a, EncounterTextures>,
        ReadStorage<'a, Draw>,
        ReadStorage<'a, Position>,
        ReadStorage<'a, State>,
        WriteStorage<'a, Body>,
        WriteStorage<'a, Weapon>,
    );

    fn run(
        &mut self,
        (
            collision_boxes,
            encounter_textures,
            draw,
            position,
            state,
            mut body,
            mut weapon,
        ): Self::SystemData,
    ) {
        use specs::Join;
        let collision_data = &collision_boxes.data;
        let textures = &encounter_textures.data;
        for (draw, position, state, body, weapon) in
            (&draw, &position, &state, &mut body, &mut weapon).join()
        {
            let mut weapon_boxes: Vec<Points> = vec![];
            let mut body_boxes: Vec<CollisionBox> = vec![];
            for image in draw.frame.images.iter() {
                match image.image_type {
                    ImageType::Collider => {
                        if let Some(collision_points) = collision_data.get(&image.sheet) {
                            if let Some(points) = &collision_points.points[image.image] {
                                let mut image_global_x: i32 =
                                    position.x as i32 + image.x * state.direction as i32;
                                let image_global_y: i32 = position.y as i32 + image.y;
                                image_global_x = match state.direction {
                                    Facing::Left => image_global_x - points.max_x as i32,
                                    Facing::Right => image_global_x,
                                };
                                weapon_boxes.push(Points {
                                    bounding: Rect {
                                        // x: image.x * state.direction as i32,
                                        // y: image.y,
                                        x: image_global_x,
                                        y: image_global_y,
                                        w: points.max_x,
                                        h: points.max_y,
                                    },
                                    points: points
                                        .data
                                        .iter()
                                        .map(|p| Point {
                                            x: image_global_x + p.x * state.direction as i32,
                                            y: image_global_y + p.y,
                                            // x: p.x * state.direction as i32,
                                            // y: p.y,
                                        })
                                        .collect(),
                                })
                            }
                        }
                    }
                    ImageType::Collidee => {
                        if let Some(texture) = textures.get(&image.sheet) {
                            let rect = &texture.rects[image.image];
                            let mut image_global_x: i32 =
                                position.x as i32 + image.x * state.direction as i32;
                            image_global_x = match state.direction {
                                Facing::Left => image_global_x - rect.w as i32,
                                Facing::Right => image_global_x,
                            };
                            body_boxes.push(CollisionBox {
                                rect: Rect {
                                    x: image_global_x,
                                    y: position.y as i32 + image.y,
                                    w: rect.w,
                                    h: rect.h,
                                },
                                sheet: image.sheet.clone(),
                                image_num: image.image as u32,
                            })
                        }
                    }
                    _ => (),
                }
            }

            if weapon_boxes.is_empty() {
                weapon.collision_points = None;
            } else {
                weapon.collision_points = Some(weapon_boxes);
            }

            if body_boxes.is_empty() {
                body.collision_boxes = None;
            } else {
                body.collision_boxes = Some(body_boxes);
            }
        }
    }
}

pub struct CheckCollisions;

impl<'a> System<'a> for CheckCollisions {
    type SystemData = (
        Read<'a, EncounterTextures>,
        ReadStorage<'a, State>,
        ReadStorage<'a, Position>,
        ReadStorage<'a, Body>,
        ReadStorage<'a, Weapon>,
        Entities<'a>,
    );

    fn run(
        &mut self,
        (encounter_textures, state, position, bodies, weapons, entities): Self::SystemData,
    ) {
        use specs::Join;
        let textures = &encounter_textures.data;
        for (state, att_pos, weapon, attacker) in (&state, &position, &weapons, &*entities)
            .join()
            .filter(|(s, ..)| s.action.is_attack())
        {
            for (defender, body, defender_position) in (&*entities, &bodies, &position)
                .join()
                // ignore self for collision checking.
                .filter(|(defender, ..)| attacker.id() != defender.id())
                // ignore entities outside a 10 pixel y range.
                .filter(|(_, _, d_pos)| (att_pos.y as i32 - d_pos.y as i32).abs() < 10)
            {
                let hit = check_collision(&textures, weapon, body);
                if hit {
                    println!("hit");
                }
            }
        }
    }
}

fn check_collision(textures: &HashMap<String, TextureAtlas>, weapon: &Weapon, body: &Body) -> bool {
    for weapon_part in weapon.collision_points.iter().flat_map(|v| v) {
        // each attacking image in the attacker
        for body_part in body
            .collision_boxes
            .iter() // Option.iter()
            .flat_map(|v| v)
            .filter(|b| weapon_part.bounding.intersects(&b.rect))
        {
            // check that against each defending image in the defender
            for point in weapon_part
                .points
                .iter()
                .filter(|p| body_part.rect.contains_point(p))
            {
                // check the points collide and the pixel in the image is a part of the target
                let hit_x = point.x - body_part.rect.x;
                let hit_y = point.y - body_part.rect.y;
                let texture = textures
                    .get(&body_part.sheet)
                    .expect("Encounter hasn't loaded correct textures to as world resource");
                let collision_lookup = hit_x as usize * texture.image.width + hit_y as usize;
                let pixel = texture.image.pixels[collision_lookup];
                if pixel > 0 {
                    return true;
                }
            }
        }
    }
    false
}
<|endoftext|>