<commit_before>pub mod basic_particle;
pub use self::basic_particle::*;

extern crate num;
use self::num::Float;
use super::vector::*;

///An object that has quanta
pub trait Quanta<D> {
    //Retrieve the quanta of a physics particle.
    fn quanta(&self) -> D;
}

///An object that has inertia
pub trait Inertia<D> {
    //Retrieve the inertia of a physics particle.
    fn inertia(&self) -> D;
}

///An object that has location
pub trait Position<V> {
    //Get position of particle.
    fn position(&self) -> V;
}

///An object that has velocity
pub trait Velocity<V> {
    //Get velocity of particle.
    fn velocity(&self) -> V;
}

///An object that has a simple particle motion interface
pub trait Particle<V, D>: Position<V> + Velocity<V> + Inertia<D> {
    ///Apply force to particle, but it isn't moved forward in time until advance is called.
    ///This requires interior mutability and unsafe declarations to fulfil.
    fn impulse(&self, vec: &V);
    ///Advance particle forward in time (update position and velocity from net force).
    fn advance(&mut self, time: D);
}

///Any particle that implements the necessary traits gains access to all of the capabilities of PhysicsParticle.
pub trait PhysicsParticle<V, D>: Particle<V, D> + Quanta<D> + Inertia<D>
    where V: Vector<D>, D: Float
{
    ///Convert a PhysicsParticle into a "basic particle" that implements PhysicsParticle but has the minimum members.
    ///Use this to implement data structures that need to create intermediary particles.
    fn basic_form(&self) -> BasicParticle<V, D> {
        BasicParticle::new(self.quanta(), self.position(), self.velocity(), self.inertia())
    }

    ///Apply drag forces to a particle.
    fn drag(&self, magnitude: D) {
        let force = -self.velocity() * magnitude;
        self.impulse(&force);
    }

    ///Apply proper attraction to a single physics particle towards a location and with a magnitude.
    fn gravitate_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where T: Quanta<D> + Position<V>
    {
        //Create delta vector from the particle to the center of attraction.
        let delta = center.position() - self.position();
        let distance = delta.displacement();
        let force = delta / distance.powi(3) * magnitude * self.quanta() * center.quanta();
        self.impulse(&force);
    }

    ///This works the same as gravitate_radius_squared and gravitate_to.
    fn gravitate_radius_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where T: Quanta<D> + Position<V> + Ball<D>
    {
        //Create delta vector from the particle to the center of attraction.
        let delta = center.position() - self.position();
        let distance_squared = delta.displacement_squared();
        let force = delta * magnitude * self.quanta() * center.quanta() /
            if distance_squared > center.radius().powi(2) {
                distance_squared.sqrt().powi(3)
            } else {
                center.radius().powi(2)
            };
        self.impulse(&force);
    }

    ///Apply spring forces between one particle and a virtual particle that is unaffected.
    fn hooke_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where T: Quanta<D> + Position<V>
    {
        let delta = center.position() - self.position();
        let force = delta.normalized() * delta.displacement() *
            magnitude * self.quanta() * center.quanta();
        self.impulse(&force);
    }

    ///Apply spring forces between one particle and a virtual particle that is unaffected.
    fn hooke_equilibrium_to<T: ?Sized>(&self, center: &T, equilibrium: D, magnitude: D)
        where T: Quanta<D> + Position<V>
    {
        let delta = center.position() - self.position();
        let force = delta.normalized() * (delta.displacement() - equilibrium) *
            magnitude * self.quanta() * center.quanta();
        self.impulse(&force);
    }

    ///Apply lorentz force to a particle in a field given by a vector with the magnitude and direction of the field.
    fn lorentz_field(&self, field: &V)
        where V: CrossVector
    {
        let force = V::cross(&self.velocity(), field) * self.quanta() / self.inertia();
        self.impulse(&force);
    }

    ///Apply the lorentz force on a virtual particle that is unaffected.
    fn lorentz_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where V: CrossVector, T: Quanta<D> + Position<V> + Velocity<V>
    {
        let delta = center.position() - self.position();
        let distance_squared = delta.displacement_squared();
        let force = V::cross(&V::cross(&self.velocity(), &delta), &center.velocity()) * magnitude *
            self.quanta() * center.quanta() / distance_squared.sqrt().powi(3);

        self.impulse(&force);
    }

    ///Apply the lorentz force on a virtual particle that is unaffected.
    fn lorentz_radius_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where V: CrossVector, T: Quanta<D> + Position<V> + Velocity<V> + Ball<D>
    {
        let delta = center.position() - self.position();
        let distance_squared = delta.displacement_squared();
        let force = V::cross(&V::cross(&self.velocity(), &delta), &center.velocity()) * magnitude *
            self.quanta() * center.quanta() /
            if distance_squared > center.radius().powi(2) {
                distance_squared.sqrt().powi(3)
            } else {
                center.radius().powi(2)
            };

        self.impulse(&force);
    }
}

///Apply proper attraction between two physics particles based on their quanta and position.
pub fn gravitate<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    //Create delta vector between the two positions.
    let delta = rhs.position() - lhs.position();
    //Find the distance of the delta vector.
    let distance = delta.displacement();
    //Dividing the delta vector by the distance cubed computes attractive force as per the inverse square law.
    //The extra degree normalizes the direction vector to a unit vector.
    let force = delta * magnitude / distance.powi(3) *
    //Multiply by the two quanta of the objects to compute the final force.
    lhs.quanta() * rhs.quanta();

    //Force lhs in the direction of force.
    lhs.impulse(&force);
    //Apply the inverse force to the rhs similarly.
    rhs.impulse(&-force);
}

#[test]
fn gravitate_test() {
    type P = BasicParticle<Cartesian3<f64>, f64>;
    let mut a = P::default();
    let mut b = P::default();
    gravitate(&a, &b, 1.0);
    a.advance(1.0);
    b.advance(1.0);
}

///If gravitating at a distance greater than the net radius, then gravitational interaction is applied as if the
///particles are point particles. If the distance is less than the radius, then the interaction happens as if the
///gravitational quanta (mass) is evenly distributed and gravitational flux is used instead, which causes the
///interaction to become proportional to the radius, meaning that as the radius approaches zero, so does the force.
pub fn gravitate_radius<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D> + Ball<D>, T2: PhysicsParticle<V, D> + Ball<D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    let radius_squared = (lhs.radius() + rhs.radius()).powi(2);
    //Force is the only thing that changes from normal gravitation.
    let force = delta * magnitude * lhs.quanta() * rhs.quanta() / if distance_squared > radius_squared {
        distance_squared.sqrt().powi(3)
    } else {
        radius_squared
    };
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

///This is the same as the radius function, but the sum of the radii squared is passed separately to avoid overhead.
pub fn gravitate_radius_squared<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, radius_squared: D, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    //Force is the only thing that changes from normal gravitation.
    let force = delta * magnitude * lhs.quanta() * rhs.quanta() / if distance_squared > radius_squared {
        distance_squared.sqrt().powi(3)
    } else {
        radius_squared
    };
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

///Apply spring forces between two particles.
pub fn hooke<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let force = delta.normalized() * magnitude * delta.displacement() * lhs.quanta() * rhs.quanta();
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

#[test]
fn hooke_test() {
    type P = BasicParticle<Cartesian3<f64>, f64>;
    let mut a = P::default();
    let mut b = P::default();
    hooke(&a, &b, 1.0);
    a.advance(1.0);
    b.advance(1.0);
}

///Apply spring forces between two particles with specified equilibrium distance.
pub fn hooke_equilibrium<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, equilibrium: D, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let force = delta.normalized() * magnitude *
        //We scale such that if displacement is greater than equilibrium, the particles attract proportionally.
        //Particles with a displacement smaller than equilibrium repel each other.
        (delta.displacement() - equilibrium) *
        lhs.quanta() * rhs.quanta();
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

///Apply lorentz forces between two PhysicsParticle objects based on quanta, position, and velocity.
pub fn lorentz<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D> + CrossVector, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance = delta.displacement();
    let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) *
        lhs.quanta() * rhs.quanta() / distance.powi(3) * magnitude;

    lhs.impulse(&-force);
    rhs.impulse(&force);
}

#[test]
fn lorentz_test() {
    type P = BasicParticle<Cartesian3<f64>, f64>;
    let mut a = P::default();
    let mut b = P::default();
    lorentz(&a, &b, 1.0);
    a.advance(1.0);
    b.advance(1.0);
}

///Apply lorentz forces between two PhysicsParticle + Ball objects assuming uniformly distributed quanta.
pub fn lorentz_radius<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D> + Ball<D>, T2: PhysicsParticle<V, D> + Ball<D>, V: Vector<D> + CrossVector, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    let radius_squared = (lhs.radius() + rhs.radius()).powi(2);
    let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) * magnitude *
        lhs.quanta() * rhs.quanta() /
        if distance_squared > radius_squared {
            distance_squared.sqrt().powi(3)
        } else {
            radius_squared
        };

    lhs.impulse(&-force);
    rhs.impulse(&force);
}

///Apply lorentz forces between two PhysicsParticle objects using a precomputed net radius.
pub fn lorentz_radius_squared<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, radius_squared: D, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D> + CrossVector, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) * magnitude *
        lhs.quanta() * rhs.quanta() /
        if distance_squared > radius_squared {
            distance_squared.sqrt().powi(3)
        } else {
            radius_squared
        };

    lhs.impulse(&-force);
    rhs.impulse(&force);
}
<commit_msg>fix for non-normal distances test<commit_after>pub mod basic_particle;
pub use self::basic_particle::*;

extern crate num;
use self::num::Float;
use super::vector::*;

///An object that has quanta
pub trait Quanta<D> {
    //Retrieve the quanta of a physics particle.
    fn quanta(&self) -> D;
}

///An object that has inertia
pub trait Inertia<D> {
    //Retrieve the inertia of a physics particle.
    fn inertia(&self) -> D;
}

///An object that has location
pub trait Position<V> {
    //Get position of particle.
    fn position(&self) -> V;
}

///An object that has velocity
pub trait Velocity<V> {
    //Get velocity of particle.
    fn velocity(&self) -> V;
}

///An object that has a simple particle motion interface
pub trait Particle<V, D>: Position<V> + Velocity<V> + Inertia<D> {
    ///Apply force to particle, but it isn't moved forward in time until advance is called.
    ///This requires interior mutability and unsafe declarations to fulfil.
    fn impulse(&self, vec: &V);
    ///Advance particle forward in time (update position and velocity from net force).
    fn advance(&mut self, time: D);
}

///Any particle that implements the necessary traits gains access to all of the capabilities of PhysicsParticle.
pub trait PhysicsParticle<V, D>: Particle<V, D> + Quanta<D> + Inertia<D>
    where V: Vector<D>, D: Float
{
    ///Convert a PhysicsParticle into a "basic particle" that implements PhysicsParticle but has the minimum members.
    ///Use this to implement data structures that need to create intermediary particles.
    fn basic_form(&self) -> BasicParticle<V, D> {
        BasicParticle::new(self.quanta(), self.position(), self.velocity(), self.inertia())
    }

    ///Apply drag forces to a particle.
    fn drag(&self, magnitude: D) {
        let force = -self.velocity() * magnitude;
        self.impulse(&force);
    }

    ///Apply proper attraction to a single physics particle towards a location and with a magnitude.
    fn gravitate_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where T: Quanta<D> + Position<V>
    {
        //Create delta vector from the particle to the center of attraction.
        let delta = center.position() - self.position();
        let distance = delta.displacement();
        let force = delta / distance.powi(3) * magnitude * self.quanta() * center.quanta();
        self.impulse(&force);
    }

    ///This works the same as gravitate_radius_squared and gravitate_to.
    fn gravitate_radius_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where T: Quanta<D> + Position<V> + Ball<D>
    {
        //Create delta vector from the particle to the center of attraction.
        let delta = center.position() - self.position();
        let distance_squared = delta.displacement_squared();
        let force = delta * magnitude * self.quanta() * center.quanta() /
            if distance_squared > center.radius().powi(2) {
                distance_squared.sqrt().powi(3)
            } else {
                center.radius().powi(2)
            };
        self.impulse(&force);
    }

    ///Apply spring forces between one particle and a virtual particle that is unaffected.
    fn hooke_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where T: Quanta<D> + Position<V>
    {
        let delta = center.position() - self.position();
        let mag = delta.displacement();
        if mag.is_normal() {
            let force = delta / mag * delta.displacement() *
                magnitude * self.quanta() * center.quanta();
            self.impulse(&force);
        }
    }

    ///Apply spring forces between one particle and a virtual particle that is unaffected.
    fn hooke_equilibrium_to<T: ?Sized>(&self, center: &T, equilibrium: D, magnitude: D)
        where T: Quanta<D> + Position<V>
    {
        let delta = center.position() - self.position();
        let force = delta.normalized() * (delta.displacement() - equilibrium) *
            magnitude * self.quanta() * center.quanta();
        self.impulse(&force);
    }

    ///Apply lorentz force to a particle in a field given by a vector with the magnitude and direction of the field.
    fn lorentz_field(&self, field: &V)
        where V: CrossVector
    {
        let force = V::cross(&self.velocity(), field) * self.quanta() / self.inertia();
        self.impulse(&force);
    }

    ///Apply the lorentz force on a virtual particle that is unaffected.
    fn lorentz_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where V: CrossVector, T: Quanta<D> + Position<V> + Velocity<V>
    {
        let delta = center.position() - self.position();
        let distance_squared = delta.displacement_squared();
        let force = V::cross(&V::cross(&self.velocity(), &delta), &center.velocity()) * magnitude *
            self.quanta() * center.quanta() / distance_squared.sqrt().powi(3);

        self.impulse(&force);
    }

    ///Apply the lorentz force on a virtual particle that is unaffected.
    fn lorentz_radius_to<T: ?Sized>(&self, center: &T, magnitude: D)
        where V: CrossVector, T: Quanta<D> + Position<V> + Velocity<V> + Ball<D>
    {
        let delta = center.position() - self.position();
        let distance_squared = delta.displacement_squared();
        let force = V::cross(&V::cross(&self.velocity(), &delta), &center.velocity()) * magnitude *
            self.quanta() * center.quanta() /
            if distance_squared > center.radius().powi(2) {
                distance_squared.sqrt().powi(3)
            } else {
                center.radius().powi(2)
            };

        self.impulse(&force);
    }
}

///Apply proper attraction between two physics particles based on their quanta and position.
pub fn gravitate<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    //Create delta vector between the two positions.
    let delta = rhs.position() - lhs.position();
    //Find the distance of the delta vector.
    let distance = delta.displacement();
    //Dividing the delta vector by the distance cubed computes attractive force as per the inverse square law.
    //The extra degree normalizes the direction vector to a unit vector.
    let force = delta * magnitude / distance.powi(3) *
    //Multiply by the two quanta of the objects to compute the final force.
    lhs.quanta() * rhs.quanta();

    //Force lhs in the direction of force.
    lhs.impulse(&force);
    //Apply the inverse force to the rhs similarly.
    rhs.impulse(&-force);
}

#[test]
fn gravitate_test() {
    type P = BasicParticle<Cartesian3<f64>, f64>;
    let mut a = P::default();
    let mut b = P::default();
    gravitate(&a, &b, 1.0);
    a.advance(1.0);
    b.advance(1.0);
}

///If gravitating at a distance greater than the net radius, then gravitational interaction is applied as if the
///particles are point particles. If the distance is less than the radius, then the interaction happens as if the
///gravitational quanta (mass) is evenly distributed and gravitational flux is used instead, which causes the
///interaction to become proportional to the radius, meaning that as the radius approaches zero, so does the force.
pub fn gravitate_radius<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D> + Ball<D>, T2: PhysicsParticle<V, D> + Ball<D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    let radius_squared = (lhs.radius() + rhs.radius()).powi(2);
    //Force is the only thing that changes from normal gravitation.
    let force = delta * magnitude * lhs.quanta() * rhs.quanta() / if distance_squared > radius_squared {
        distance_squared.sqrt().powi(3)
    } else {
        radius_squared
    };
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

///This is the same as the radius function, but the sum of the radii squared is passed separately to avoid overhead.
pub fn gravitate_radius_squared<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, radius_squared: D, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    //Force is the only thing that changes from normal gravitation.
    let force = delta * magnitude * lhs.quanta() * rhs.quanta() / if distance_squared > radius_squared {
        distance_squared.sqrt().powi(3)
    } else {
        radius_squared
    };
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

///Apply spring forces between two particles.
pub fn hooke<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let force = delta.normalized() * magnitude * delta.displacement() * lhs.quanta() * rhs.quanta();
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

#[test]
fn hooke_test() {
    type P = BasicParticle<Cartesian3<f64>, f64>;
    let mut a = P::default();
    let mut b = P::default();
    hooke(&a, &b, 1.0);
    a.advance(1.0);
    b.advance(1.0);
}

///Apply spring forces between two particles with specified equilibrium distance.
pub fn hooke_equilibrium<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, equilibrium: D, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D>, D: Float
{
    let delta = rhs.position() - lhs.position();
    let force = delta.normalized() * magnitude *
        //We scale such that if displacement is greater than equilibrium, the particles attract proportionally.
        //Particles with a displacement smaller than equilibrium repel each other.
        (delta.displacement() - equilibrium) *
        lhs.quanta() * rhs.quanta();
    lhs.impulse(&force);
    rhs.impulse(&-force);
}

///Apply lorentz forces between two PhysicsParticle objects based on quanta, position, and velocity.
pub fn lorentz<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D> + CrossVector, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance = delta.displacement();
    let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) *
        lhs.quanta() * rhs.quanta() / distance.powi(3) * magnitude;

    lhs.impulse(&-force);
    rhs.impulse(&force);
}

#[test]
fn lorentz_test() {
    type P = BasicParticle<Cartesian3<f64>, f64>;
    let mut a = P::default();
    let mut b = P::default();
    lorentz(&a, &b, 1.0);
    a.advance(1.0);
    b.advance(1.0);
}

///Apply lorentz forces between two PhysicsParticle + Ball objects assuming uniformly distributed quanta.
pub fn lorentz_radius<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, magnitude: D)
    where T1: PhysicsParticle<V, D> + Ball<D>, T2: PhysicsParticle<V, D> + Ball<D>, V: Vector<D> + CrossVector, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    let radius_squared = (lhs.radius() + rhs.radius()).powi(2);
    let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) * magnitude *
        lhs.quanta() * rhs.quanta() /
        if distance_squared > radius_squared {
            distance_squared.sqrt().powi(3)
        } else {
            radius_squared
        };

    lhs.impulse(&-force);
    rhs.impulse(&force);
}

///Apply lorentz forces between two PhysicsParticle objects using a precomputed net radius.
pub fn lorentz_radius_squared<V, D, T1: ?Sized, T2: ?Sized>(lhs: &T1, rhs: &T2, radius_squared: D, magnitude: D)
    where T1: PhysicsParticle<V, D>, T2: PhysicsParticle<V, D>, V: Vector<D> + CrossVector, D: Float
{
    let delta = rhs.position() - lhs.position();
    let distance_squared = delta.displacement_squared();
    let force = V::cross(&rhs.velocity(), &V::cross(&lhs.velocity(), &delta)) * magnitude *
        lhs.quanta() * rhs.quanta() /
        if distance_squared > radius_squared {
            distance_squared.sqrt().powi(3)
        } else {
            radius_squared
        };

    lhs.impulse(&-force);
    rhs.impulse(&force);
}
<|endoftext|>


<commit_before><commit_msg>Subroutines<commit_after><|endoftext|>


<commit_before>
<commit_msg>All enums and constants are now in the modbus.rs file concentrated<commit_after><|endoftext|>


<commit_before>use std::error;
use std::fmt;
use std::io;

use c_ares;

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Ares(c_ares::Error),
}

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

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref err) => err.description(),
            Error::Ares(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Io(ref err) => Some(err),
            Error::Ares(ref err) => Some(err),
        }
    }
}

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

impl From<c_ares::Error> for Error {
    fn from(err: c_ares::Error) -> Error {
        Error::Ares(err)
    }
}
<commit_msg>Docs and deriving on<commit_after>use std::error;
use std::fmt;
use std::io;

use c_ares;

/// Error codes that the library might return.
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub enum Error {
    /// An `io::Error`.
    Io(io::Error),

    /// A `c_ares::Error`.
    Ares(c_ares::Error),
}

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

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref err) => err.description(),
            Error::Ares(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Io(ref err) => Some(err),
            Error::Ares(ref err) => Some(err),
        }
    }
}

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

impl From<c_ares::Error> for Error {
    fn from(err: c_ares::Error) -> Error {
        Error::Ares(err)
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// ignore-lexer-test FIXME #15679

//! The Gamma and derived distributions.

use self::GammaRepr::*;
use self::ChiSquaredRepr::*;

use {Rng};
use distributions::normal::StandardNormal;
use distributions::{Distribution, Exp, Uniform};

/// The Gamma distribution `Gamma(shape, scale)` distribution.
///
/// The density function of this distribution is
///
/// ```text
/// f(x) =  x^(k - 1) * exp(-x / θ) / (Γ(k) * θ^k)
/// ```
///
/// where `Γ` is the Gamma function, `k` is the shape and `θ` is the
/// scale and both `k` and `θ` are strictly positive.
///
/// The algorithm used is that described by Marsaglia & Tsang 2000[1],
/// falling back to directly sampling from an Exponential for `shape
/// == 1`, and using the boosting technique described in [1] for
/// `shape < 1`.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{Distribution, Gamma};
///
/// let gamma = Gamma::new(2.0, 5.0);
/// let v = gamma.sample(&mut rand::thread_rng());
/// println!("{} is from a Gamma(2, 5) distribution", v);
/// ```
///
/// [1]: George Marsaglia and Wai Wan Tsang. 2000. "A Simple Method
/// for Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3
/// (September 2000),
/// 363-372. DOI:[10.1145/358407.358414](https://doi.acm.org/10.1145/358407.358414)
#[derive(Clone, Copy, Debug)]
pub struct Gamma {
    repr: GammaRepr,
}

#[derive(Clone, Copy, Debug)]
enum GammaRepr {
    Large(GammaLargeShape),
    One(Exp),
    Small(GammaSmallShape)
}

// These two helpers could be made public, but saving the
// match-on-Gamma-enum branch from using them directly (e.g. if one
// knows that the shape is always > 1) doesn't appear to be much
// faster.

/// Gamma distribution where the shape parameter is less than 1.
///
/// Note, samples from this require a compulsory floating-point `pow`
/// call, which makes it significantly slower than sampling from a
/// gamma distribution where the shape parameter is greater than or
/// equal to 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
#[derive(Clone, Copy, Debug)]
struct GammaSmallShape {
    inv_shape: f64,
    large_shape: GammaLargeShape
}

/// Gamma distribution where the shape parameter is larger than 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
#[derive(Clone, Copy, Debug)]
struct GammaLargeShape {
    scale: f64,
    c: f64,
    d: f64
}

impl Gamma {
    /// Construct an object representing the `Gamma(shape, scale)`
    /// distribution.
    ///
    /// Panics if `shape <= 0` or `scale <= 0`.
    #[inline]
    pub fn new(shape: f64, scale: f64) -> Gamma {
        assert!(shape > 0.0, "Gamma::new called with shape <= 0");
        assert!(scale > 0.0, "Gamma::new called with scale <= 0");

        let repr = if shape == 1.0 {
            One(Exp::new(1.0 / scale))
        } else if shape < 1.0 {
            Small(GammaSmallShape::new_raw(shape, scale))
        } else {
            Large(GammaLargeShape::new_raw(shape, scale))
        };
        Gamma { repr }
    }
}

impl GammaSmallShape {
    fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
        GammaSmallShape {
            inv_shape: 1. / shape,
            large_shape: GammaLargeShape::new_raw(shape + 1.0, scale)
        }
    }
}

impl GammaLargeShape {
    fn new_raw(shape: f64, scale: f64) -> GammaLargeShape {
        let d = shape - 1. / 3.;
        GammaLargeShape {
            scale,
            c: 1. / (9. * d).sqrt(),
            d
        }
    }
}

impl Distribution<f64> for Gamma {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        match self.repr {
            Small(ref g) => g.sample(rng),
            One(ref g) => g.sample(rng),
            Large(ref g) => g.sample(rng),
        }
    }
}
impl Distribution<f64> for GammaSmallShape {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        let u: f64 = rng.sample(Uniform);

        self.large_shape.sample(rng) * u.powf(self.inv_shape)
    }
}
impl Distribution<f64> for GammaLargeShape {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        loop {
            let x = rng.sample(StandardNormal);
            let v_cbrt = 1.0 + self.c * x;
            if v_cbrt <= 0.0 { // a^3 <= 0 iff a <= 0
                continue
            }

            let v = v_cbrt * v_cbrt * v_cbrt;
            let u: f64 = rng.sample(Uniform);

            let x_sqr = x * x;
            if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
                u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
                return self.d * v * self.scale
            }
        }
    }
}

/// The chi-squared distribution `χ²(k)`, where `k` is the degrees of
/// freedom.
///
/// For `k > 0` integral, this distribution is the sum of the squares
/// of `k` independent standard normal random variables. For other
/// `k`, this uses the equivalent characterisation
/// `χ²(k) = Gamma(k/2, 2)`.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{ChiSquared, Distribution};
///
/// let chi = ChiSquared::new(11.0);
/// let v = chi.sample(&mut rand::thread_rng());
/// println!("{} is from a χ²(11) distribution", v)
/// ```
#[derive(Clone, Copy, Debug)]
pub struct ChiSquared {
    repr: ChiSquaredRepr,
}

#[derive(Clone, Copy, Debug)]
enum ChiSquaredRepr {
    // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1,
    // e.g. when alpha = 1/2 as it would be for this case, so special-
    // casing and using the definition of N(0,1)^2 is faster.
    DoFExactlyOne,
    DoFAnythingElse(Gamma),
}

impl ChiSquared {
    /// Create a new chi-squared distribution with degrees-of-freedom
    /// `k`. Panics if `k < 0`.
    pub fn new(k: f64) -> ChiSquared {
        let repr = if k == 1.0 {
            DoFExactlyOne
        } else {
            assert!(k > 0.0, "ChiSquared::new called with `k` < 0");
            DoFAnythingElse(Gamma::new(0.5 * k, 2.0))
        };
        ChiSquared { repr }
    }
}
impl Distribution<f64> for ChiSquared {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        match self.repr {
            DoFExactlyOne => {
                // k == 1 => N(0,1)^2
                let norm = rng.sample(StandardNormal);
                norm * norm
            }
            DoFAnythingElse(ref g) => g.sample(rng)
        }
    }
}

/// The Fisher F distribution `F(m, n)`.
///
/// This distribution is equivalent to the ratio of two normalised
/// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) /
/// (χ²(n)/n)`.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{FisherF, Distribution};
///
/// let f = FisherF::new(2.0, 32.0);
/// let v = f.sample(&mut rand::thread_rng());
/// println!("{} is from an F(2, 32) distribution", v)
/// ```
#[derive(Clone, Copy, Debug)]
pub struct FisherF {
    numer: ChiSquared,
    denom: ChiSquared,
    // denom_dof / numer_dof so that this can just be a straight
    // multiplication, rather than a division.
    dof_ratio: f64,
}

impl FisherF {
    /// Create a new `FisherF` distribution, with the given
    /// parameter. Panics if either `m` or `n` are not positive.
    pub fn new(m: f64, n: f64) -> FisherF {
        assert!(m > 0.0, "FisherF::new called with `m < 0`");
        assert!(n > 0.0, "FisherF::new called with `n < 0`");

        FisherF {
            numer: ChiSquared::new(m),
            denom: ChiSquared::new(n),
            dof_ratio: n / m
        }
    }
}
impl Distribution<f64> for FisherF {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        self.numer.sample(rng) / self.denom.sample(rng) * self.dof_ratio
    }
}

/// The Student t distribution, `t(nu)`, where `nu` is the degrees of
/// freedom.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{StudentT, Distribution};
///
/// let t = StudentT::new(11.0);
/// let v = t.sample(&mut rand::thread_rng());
/// println!("{} is from a t(11) distribution", v)
/// ```
#[derive(Clone, Copy, Debug)]
pub struct StudentT {
    chi: ChiSquared,
    dof: f64
}

impl StudentT {
    /// Create a new Student t distribution with `n` degrees of
    /// freedom. Panics if `n <= 0`.
    pub fn new(n: f64) -> StudentT {
        assert!(n > 0.0, "StudentT::new called with `n <= 0`");
        StudentT {
            chi: ChiSquared::new(n),
            dof: n
        }
    }
}
impl Distribution<f64> for StudentT {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        let norm = rng.sample(StandardNormal);
        norm * (self.dof / self.chi.sample(rng)).sqrt()
    }
}

#[cfg(test)]
mod test {
    use distributions::Distribution;
    use super::{ChiSquared, StudentT, FisherF};

    #[test]
    fn test_chi_squared_one() {
        let chi = ChiSquared::new(1.0);
        let mut rng = ::test::rng(201);
        for _ in 0..1000 {
            chi.sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_small() {
        let chi = ChiSquared::new(0.5);
        let mut rng = ::test::rng(202);
        for _ in 0..1000 {
            chi.sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_large() {
        let chi = ChiSquared::new(30.0);
        let mut rng = ::test::rng(203);
        for _ in 0..1000 {
            chi.sample(&mut rng);
        }
    }
    #[test]
    #[should_panic]
    fn test_chi_squared_invalid_dof() {
        ChiSquared::new(-1.0);
    }

    #[test]
    fn test_f() {
        let f = FisherF::new(2.0, 32.0);
        let mut rng = ::test::rng(204);
        for _ in 0..1000 {
            f.sample(&mut rng);
        }
    }

    #[test]
    fn test_t() {
        let t = StudentT::new(11.0);
        let mut rng = ::test::rng(205);
        for _ in 0..1000 {
            t.sample(&mut rng);
        }
    }
}
<commit_msg>Remove obsolete fixme<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Gamma and derived distributions.

use self::GammaRepr::*;
use self::ChiSquaredRepr::*;

use {Rng};
use distributions::normal::StandardNormal;
use distributions::{Distribution, Exp, Uniform};

/// The Gamma distribution `Gamma(shape, scale)` distribution.
///
/// The density function of this distribution is
///
/// ```text
/// f(x) =  x^(k - 1) * exp(-x / θ) / (Γ(k) * θ^k)
/// ```
///
/// where `Γ` is the Gamma function, `k` is the shape and `θ` is the
/// scale and both `k` and `θ` are strictly positive.
///
/// The algorithm used is that described by Marsaglia & Tsang 2000[1],
/// falling back to directly sampling from an Exponential for `shape
/// == 1`, and using the boosting technique described in [1] for
/// `shape < 1`.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{Distribution, Gamma};
///
/// let gamma = Gamma::new(2.0, 5.0);
/// let v = gamma.sample(&mut rand::thread_rng());
/// println!("{} is from a Gamma(2, 5) distribution", v);
/// ```
///
/// [1]: George Marsaglia and Wai Wan Tsang. 2000. "A Simple Method
/// for Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3
/// (September 2000),
/// 363-372. DOI:[10.1145/358407.358414](https://doi.acm.org/10.1145/358407.358414)
#[derive(Clone, Copy, Debug)]
pub struct Gamma {
    repr: GammaRepr,
}

#[derive(Clone, Copy, Debug)]
enum GammaRepr {
    Large(GammaLargeShape),
    One(Exp),
    Small(GammaSmallShape)
}

// These two helpers could be made public, but saving the
// match-on-Gamma-enum branch from using them directly (e.g. if one
// knows that the shape is always > 1) doesn't appear to be much
// faster.

/// Gamma distribution where the shape parameter is less than 1.
///
/// Note, samples from this require a compulsory floating-point `pow`
/// call, which makes it significantly slower than sampling from a
/// gamma distribution where the shape parameter is greater than or
/// equal to 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
#[derive(Clone, Copy, Debug)]
struct GammaSmallShape {
    inv_shape: f64,
    large_shape: GammaLargeShape
}

/// Gamma distribution where the shape parameter is larger than 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
#[derive(Clone, Copy, Debug)]
struct GammaLargeShape {
    scale: f64,
    c: f64,
    d: f64
}

impl Gamma {
    /// Construct an object representing the `Gamma(shape, scale)`
    /// distribution.
    ///
    /// Panics if `shape <= 0` or `scale <= 0`.
    #[inline]
    pub fn new(shape: f64, scale: f64) -> Gamma {
        assert!(shape > 0.0, "Gamma::new called with shape <= 0");
        assert!(scale > 0.0, "Gamma::new called with scale <= 0");

        let repr = if shape == 1.0 {
            One(Exp::new(1.0 / scale))
        } else if shape < 1.0 {
            Small(GammaSmallShape::new_raw(shape, scale))
        } else {
            Large(GammaLargeShape::new_raw(shape, scale))
        };
        Gamma { repr }
    }
}

impl GammaSmallShape {
    fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
        GammaSmallShape {
            inv_shape: 1. / shape,
            large_shape: GammaLargeShape::new_raw(shape + 1.0, scale)
        }
    }
}

impl GammaLargeShape {
    fn new_raw(shape: f64, scale: f64) -> GammaLargeShape {
        let d = shape - 1. / 3.;
        GammaLargeShape {
            scale,
            c: 1. / (9. * d).sqrt(),
            d
        }
    }
}

impl Distribution<f64> for Gamma {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        match self.repr {
            Small(ref g) => g.sample(rng),
            One(ref g) => g.sample(rng),
            Large(ref g) => g.sample(rng),
        }
    }
}
impl Distribution<f64> for GammaSmallShape {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        let u: f64 = rng.sample(Uniform);

        self.large_shape.sample(rng) * u.powf(self.inv_shape)
    }
}
impl Distribution<f64> for GammaLargeShape {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        loop {
            let x = rng.sample(StandardNormal);
            let v_cbrt = 1.0 + self.c * x;
            if v_cbrt <= 0.0 { // a^3 <= 0 iff a <= 0
                continue
            }

            let v = v_cbrt * v_cbrt * v_cbrt;
            let u: f64 = rng.sample(Uniform);

            let x_sqr = x * x;
            if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
                u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
                return self.d * v * self.scale
            }
        }
    }
}

/// The chi-squared distribution `χ²(k)`, where `k` is the degrees of
/// freedom.
///
/// For `k > 0` integral, this distribution is the sum of the squares
/// of `k` independent standard normal random variables. For other
/// `k`, this uses the equivalent characterisation
/// `χ²(k) = Gamma(k/2, 2)`.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{ChiSquared, Distribution};
///
/// let chi = ChiSquared::new(11.0);
/// let v = chi.sample(&mut rand::thread_rng());
/// println!("{} is from a χ²(11) distribution", v)
/// ```
#[derive(Clone, Copy, Debug)]
pub struct ChiSquared {
    repr: ChiSquaredRepr,
}

#[derive(Clone, Copy, Debug)]
enum ChiSquaredRepr {
    // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1,
    // e.g. when alpha = 1/2 as it would be for this case, so special-
    // casing and using the definition of N(0,1)^2 is faster.
    DoFExactlyOne,
    DoFAnythingElse(Gamma),
}

impl ChiSquared {
    /// Create a new chi-squared distribution with degrees-of-freedom
    /// `k`. Panics if `k < 0`.
    pub fn new(k: f64) -> ChiSquared {
        let repr = if k == 1.0 {
            DoFExactlyOne
        } else {
            assert!(k > 0.0, "ChiSquared::new called with `k` < 0");
            DoFAnythingElse(Gamma::new(0.5 * k, 2.0))
        };
        ChiSquared { repr }
    }
}
impl Distribution<f64> for ChiSquared {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        match self.repr {
            DoFExactlyOne => {
                // k == 1 => N(0,1)^2
                let norm = rng.sample(StandardNormal);
                norm * norm
            }
            DoFAnythingElse(ref g) => g.sample(rng)
        }
    }
}

/// The Fisher F distribution `F(m, n)`.
///
/// This distribution is equivalent to the ratio of two normalised
/// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) /
/// (χ²(n)/n)`.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{FisherF, Distribution};
///
/// let f = FisherF::new(2.0, 32.0);
/// let v = f.sample(&mut rand::thread_rng());
/// println!("{} is from an F(2, 32) distribution", v)
/// ```
#[derive(Clone, Copy, Debug)]
pub struct FisherF {
    numer: ChiSquared,
    denom: ChiSquared,
    // denom_dof / numer_dof so that this can just be a straight
    // multiplication, rather than a division.
    dof_ratio: f64,
}

impl FisherF {
    /// Create a new `FisherF` distribution, with the given
    /// parameter. Panics if either `m` or `n` are not positive.
    pub fn new(m: f64, n: f64) -> FisherF {
        assert!(m > 0.0, "FisherF::new called with `m < 0`");
        assert!(n > 0.0, "FisherF::new called with `n < 0`");

        FisherF {
            numer: ChiSquared::new(m),
            denom: ChiSquared::new(n),
            dof_ratio: n / m
        }
    }
}
impl Distribution<f64> for FisherF {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        self.numer.sample(rng) / self.denom.sample(rng) * self.dof_ratio
    }
}

/// The Student t distribution, `t(nu)`, where `nu` is the degrees of
/// freedom.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{StudentT, Distribution};
///
/// let t = StudentT::new(11.0);
/// let v = t.sample(&mut rand::thread_rng());
/// println!("{} is from a t(11) distribution", v)
/// ```
#[derive(Clone, Copy, Debug)]
pub struct StudentT {
    chi: ChiSquared,
    dof: f64
}

impl StudentT {
    /// Create a new Student t distribution with `n` degrees of
    /// freedom. Panics if `n <= 0`.
    pub fn new(n: f64) -> StudentT {
        assert!(n > 0.0, "StudentT::new called with `n <= 0`");
        StudentT {
            chi: ChiSquared::new(n),
            dof: n
        }
    }
}
impl Distribution<f64> for StudentT {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        let norm = rng.sample(StandardNormal);
        norm * (self.dof / self.chi.sample(rng)).sqrt()
    }
}

#[cfg(test)]
mod test {
    use distributions::Distribution;
    use super::{ChiSquared, StudentT, FisherF};

    #[test]
    fn test_chi_squared_one() {
        let chi = ChiSquared::new(1.0);
        let mut rng = ::test::rng(201);
        for _ in 0..1000 {
            chi.sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_small() {
        let chi = ChiSquared::new(0.5);
        let mut rng = ::test::rng(202);
        for _ in 0..1000 {
            chi.sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_large() {
        let chi = ChiSquared::new(30.0);
        let mut rng = ::test::rng(203);
        for _ in 0..1000 {
            chi.sample(&mut rng);
        }
    }
    #[test]
    #[should_panic]
    fn test_chi_squared_invalid_dof() {
        ChiSquared::new(-1.0);
    }

    #[test]
    fn test_f() {
        let f = FisherF::new(2.0, 32.0);
        let mut rng = ::test::rng(204);
        for _ in 0..1000 {
            f.sample(&mut rng);
        }
    }

    #[test]
    fn test_t() {
        let t = StudentT::new(11.0);
        let mut rng = ::test::rng(205);
        for _ in 0..1000 {
            t.sample(&mut rng);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The implementations of the `Standard` distribution for other built-in types.

use core::char;
use core::num::Wrapping;

use crate::distributions::{Distribution, Standard, Uniform};
use crate::Rng;

#[cfg(feature = "serde1")]
use serde::{Serialize, Deserialize};

// ----- Sampling distributions -----

/// Sample a `char`, uniformly distributed over ASCII letters and numbers:
/// a-z, A-Z and 0-9.
///
/// # Example
///
/// ```
/// use std::iter;
/// use rand::{Rng, thread_rng};
/// use rand::distributions::Alphanumeric;
///
/// let mut rng = thread_rng();
/// let chars: String = iter::repeat(())
///         .map(|()| rng.sample(Alphanumeric))
///         .take(7)
///         .collect();
/// println!("Random chars: {}", chars);
/// ```
///
/// # Passwords
///
/// Users sometimes ask whether it is safe to use a string of random characters
/// as a password. In principle, all RNGs in Rand implementing `CryptoRng` are
/// suitable as a source of randomness for generating passwords (if they are
/// properly seeded), but it is more conservative to only use randomness
/// directly from the operating system via the `getrandom` crate, or the
/// corresponding bindings of a crypto library.
///
/// When generating passwords or keys, it is important to consider the threat
/// model and in some cases the memorability of the password. This is out of
/// scope of the Rand project, and therefore we defer to the following
/// references:
///
/// - [Wikipedia article on Password Strength](https://en.wikipedia.org/wiki/Password_strength)
/// - [Diceware for generating memorable passwords](https://en.wikipedia.org/wiki/Diceware)
#[derive(Debug)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Alphanumeric;

// ----- Implementations of distributions -----

impl Distribution<char> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
        // A valid `char` is either in the interval `[0, 0xD800)` or
        // `(0xDFFF, 0x11_0000)`. All `char`s must therefore be in
        // `[0, 0x11_0000)` but not in the "gap" `[0xD800, 0xDFFF]` which is
        // reserved for surrogates. This is the size of that gap.
        const GAP_SIZE: u32 = 0xDFFF - 0xD800 + 1;

        // Uniform::new(0, 0x11_0000 - GAP_SIZE) can also be used but it
        // seemed slower.
        let range = Uniform::new(GAP_SIZE, 0x11_0000);

        let mut n = range.sample(rng);
        if n <= 0xDFFF {
            n -= GAP_SIZE;
        }
        unsafe { char::from_u32_unchecked(n) }
    }
}

impl Distribution<char> for Alphanumeric {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
        const RANGE: u32 = 26 + 26 + 10;
        const GEN_ASCII_STR_CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                abcdefghijklmnopqrstuvwxyz\
                0123456789";
        // We can pick from 62 characters. This is so close to a power of 2, 64,
        // that we can do better than `Uniform`. Use a simple bitshift and
        // rejection sampling. We do not use a bitmask, because for small RNGs
        // the most significant bits are usually of higher quality.
        loop {
            let var = rng.next_u32() >> (32 - 6);
            if var < RANGE {
                return GEN_ASCII_STR_CHARSET[var as usize] as char;
            }
        }
    }
}

impl Distribution<bool> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
        // We can compare against an arbitrary bit of an u32 to get a bool.
        // Because the least significant bits of a lower quality RNG can have
        // simple patterns, we compare against the most significant bit. This is
        // easiest done using a sign test.
        (rng.next_u32() as i32) < 0
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl< $( $tyvar ),* >
            Distribution<( $( $tyvar ),* , )>
            for Standard
            where $( Standard: Distribution<$tyvar> ),*
        {
            #[inline]
            fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Distribution<()> for Standard {
    #[allow(clippy::unused_unit)]
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> () {
        ()
    }
}
tuple_impl! {A}
tuple_impl! {A, B}
tuple_impl! {A, B, C}
tuple_impl! {A, B, C, D}
tuple_impl! {A, B, C, D, E}
tuple_impl! {A, B, C, D, E, F}
tuple_impl! {A, B, C, D, E, F, G}
tuple_impl! {A, B, C, D, E, F, G, H}
tuple_impl! {A, B, C, D, E, F, G, H, I}
tuple_impl! {A, B, C, D, E, F, G, H, I, J}
tuple_impl! {A, B, C, D, E, F, G, H, I, J, K}
tuple_impl! {A, B, C, D, E, F, G, H, I, J, K, L}

macro_rules! array_impl {
    // recursive, given at least one type parameter:
    {$n:expr, $t:ident, $($ts:ident,)*} => {
        array_impl!{($n - 1), $($ts,)*}

        impl<T> Distribution<[T; $n]> for Standard where Standard: Distribution<T> {
            #[inline]
            fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] {
                [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
            }
        }
    };
    // empty case:
    {$n:expr,} => {
        impl<T> Distribution<[T; $n]> for Standard {
            fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] { [] }
        }
    };
}

array_impl! {32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}

impl<T> Distribution<Option<T>> for Standard
where Standard: Distribution<T>
{
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<T> {
        // UFCS is needed here: https://github.com/rust-lang/rust/issues/24066
        if rng.gen::<bool>() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T> Distribution<Wrapping<T>> for Standard
where Standard: Distribution<T>
{
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Wrapping<T> {
        Wrapping(rng.gen())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::RngCore;
    #[cfg(all(not(feature = "std"), feature = "alloc"))] use alloc::string::String;

    #[test]
    fn test_misc() {
        let rng: &mut dyn RngCore = &mut crate::test::rng(820);

        rng.sample::<char, _>(Standard);
        rng.sample::<bool, _>(Standard);
    }

    #[cfg(feature = "alloc")]
    #[test]
    fn test_chars() {
        use core::iter;
        let mut rng = crate::test::rng(805);

        // Test by generating a relatively large number of chars, so we also
        // take the rejection sampling path.
        let word: String = iter::repeat(())
            .map(|()| rng.gen::<char>())
            .take(1000)
            .collect();
        assert!(word.len() != 0);
    }

    #[test]
    fn test_alphanumeric() {
        let mut rng = crate::test::rng(806);

        // Test by generating a relatively large number of chars, so we also
        // take the rejection sampling path.
        let mut incorrect = false;
        for _ in 0..100 {
            let c = rng.sample(Alphanumeric);
            incorrect |= !((c >= '0' && c <= '9') ||
                           (c >= 'A' && c <= 'Z') ||
                           (c >= 'a' && c <= 'z') );
        }
        assert!(incorrect == false);
    }

    #[test]
    fn value_stability() {
        fn test_samples<T: Copy + core::fmt::Debug + PartialEq, D: Distribution<T>>(
            distr: &D, zero: T, expected: &[T],
        ) {
            let mut rng = crate::test::rng(807);
            let mut buf = [zero; 5];
            for x in &mut buf {
                *x = rng.sample(&distr);
            }
            assert_eq!(&buf, expected);
        }

        test_samples(&Standard, 'a', &[
            '\u{8cdac}',
            '\u{a346a}',
            '\u{80120}',
            '\u{ed692}',
            '\u{35888}',
        ]);
        test_samples(&Alphanumeric, 'a', &['h', 'm', 'e', '3', 'M']);
        test_samples(&Standard, false, &[true, true, false, true, false]);
        test_samples(&Standard, None as Option<bool>, &[
            Some(true),
            None,
            Some(false),
            None,
            Some(false),
        ]);
        test_samples(&Standard, Wrapping(0i32), &[
            Wrapping(-2074640887),
            Wrapping(-1719949321),
            Wrapping(2018088303),
            Wrapping(-547181756),
            Wrapping(838957336),
        ]);

        // We test only sub-sets of tuple and array impls
        test_samples(&Standard, (), &[(), (), (), (), ()]);
        test_samples(&Standard, (false,), &[
            (true,),
            (true,),
            (false,),
            (true,),
            (false,),
        ]);
        test_samples(&Standard, (false, false), &[
            (true, true),
            (false, true),
            (false, false),
            (true, false),
            (false, false),
        ]);

        test_samples(&Standard, [0u8; 0], &[[], [], [], [], []]);
        test_samples(&Standard, [0u8; 3], &[
            [9, 247, 111],
            [68, 24, 13],
            [174, 19, 194],
            [172, 69, 213],
            [149, 207, 29],
        ]);
    }
}
<commit_msg>Impl Distribution<u8> for Alphanumeric<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The implementations of the `Standard` distribution for other built-in types.

use core::char;
use core::num::Wrapping;

use crate::distributions::{Distribution, Standard, Uniform};
use crate::Rng;

#[cfg(feature = "serde1")]
use serde::{Serialize, Deserialize};

// ----- Sampling distributions -----

/// Sample a `char` or `u8`, uniformly distributed over ASCII letters and numbers:
/// a-z, A-Z and 0-9.
///
/// # Example
///
/// ```
/// use std::iter;
/// use rand::{Rng, thread_rng};
/// use rand::distributions::Alphanumeric;
///
/// let mut rng = thread_rng();
/// let chars: String = iter::repeat(())
///         .map(|()| rng.sample(Alphanumeric))
///         .take(7)
///         .collect();
/// println!("Random chars: {}", chars);
/// ```
///
/// # Passwords
///
/// Users sometimes ask whether it is safe to use a string of random characters
/// as a password. In principle, all RNGs in Rand implementing `CryptoRng` are
/// suitable as a source of randomness for generating passwords (if they are
/// properly seeded), but it is more conservative to only use randomness
/// directly from the operating system via the `getrandom` crate, or the
/// corresponding bindings of a crypto library.
///
/// When generating passwords or keys, it is important to consider the threat
/// model and in some cases the memorability of the password. This is out of
/// scope of the Rand project, and therefore we defer to the following
/// references:
///
/// - [Wikipedia article on Password Strength](https://en.wikipedia.org/wiki/Password_strength)
/// - [Diceware for generating memorable passwords](https://en.wikipedia.org/wiki/Diceware)
#[derive(Debug)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Alphanumeric;

// ----- Implementations of distributions -----

impl Distribution<char> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
        // A valid `char` is either in the interval `[0, 0xD800)` or
        // `(0xDFFF, 0x11_0000)`. All `char`s must therefore be in
        // `[0, 0x11_0000)` but not in the "gap" `[0xD800, 0xDFFF]` which is
        // reserved for surrogates. This is the size of that gap.
        const GAP_SIZE: u32 = 0xDFFF - 0xD800 + 1;

        // Uniform::new(0, 0x11_0000 - GAP_SIZE) can also be used but it
        // seemed slower.
        let range = Uniform::new(GAP_SIZE, 0x11_0000);

        let mut n = range.sample(rng);
        if n <= 0xDFFF {
            n -= GAP_SIZE;
        }
        unsafe { char::from_u32_unchecked(n) }
    }
}

impl Distribution<char> for Alphanumeric {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
        let byte: u8 = self.sample(rng);
        byte as char
    }
}

impl Distribution<u8> for Alphanumeric {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
        const RANGE: u32 = 26 + 26 + 10;
        const GEN_ASCII_STR_CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                abcdefghijklmnopqrstuvwxyz\
                0123456789";
        // We can pick from 62 characters. This is so close to a power of 2, 64,
        // that we can do better than `Uniform`. Use a simple bitshift and
        // rejection sampling. We do not use a bitmask, because for small RNGs
        // the most significant bits are usually of higher quality.
        loop {
            let var = rng.next_u32() >> (32 - 6);
            if var < RANGE {
                return GEN_ASCII_STR_CHARSET[var as usize];
            }
        }
    }
}

impl Distribution<bool> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
        // We can compare against an arbitrary bit of an u32 to get a bool.
        // Because the least significant bits of a lower quality RNG can have
        // simple patterns, we compare against the most significant bit. This is
        // easiest done using a sign test.
        (rng.next_u32() as i32) < 0
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl< $( $tyvar ),* >
            Distribution<( $( $tyvar ),* , )>
            for Standard
            where $( Standard: Distribution<$tyvar> ),*
        {
            #[inline]
            fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Distribution<()> for Standard {
    #[allow(clippy::unused_unit)]
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> () {
        ()
    }
}
tuple_impl! {A}
tuple_impl! {A, B}
tuple_impl! {A, B, C}
tuple_impl! {A, B, C, D}
tuple_impl! {A, B, C, D, E}
tuple_impl! {A, B, C, D, E, F}
tuple_impl! {A, B, C, D, E, F, G}
tuple_impl! {A, B, C, D, E, F, G, H}
tuple_impl! {A, B, C, D, E, F, G, H, I}
tuple_impl! {A, B, C, D, E, F, G, H, I, J}
tuple_impl! {A, B, C, D, E, F, G, H, I, J, K}
tuple_impl! {A, B, C, D, E, F, G, H, I, J, K, L}

macro_rules! array_impl {
    // recursive, given at least one type parameter:
    {$n:expr, $t:ident, $($ts:ident,)*} => {
        array_impl!{($n - 1), $($ts,)*}

        impl<T> Distribution<[T; $n]> for Standard where Standard: Distribution<T> {
            #[inline]
            fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] {
                [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
            }
        }
    };
    // empty case:
    {$n:expr,} => {
        impl<T> Distribution<[T; $n]> for Standard {
            fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] { [] }
        }
    };
}

array_impl! {32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}

impl<T> Distribution<Option<T>> for Standard
where Standard: Distribution<T>
{
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<T> {
        // UFCS is needed here: https://github.com/rust-lang/rust/issues/24066
        if rng.gen::<bool>() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T> Distribution<Wrapping<T>> for Standard
where Standard: Distribution<T>
{
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Wrapping<T> {
        Wrapping(rng.gen())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::RngCore;
    #[cfg(all(not(feature = "std"), feature = "alloc"))] use alloc::string::String;

    #[test]
    fn test_misc() {
        let rng: &mut dyn RngCore = &mut crate::test::rng(820);

        rng.sample::<char, _>(Standard);
        rng.sample::<bool, _>(Standard);
    }

    #[cfg(feature = "alloc")]
    #[test]
    fn test_chars() {
        use core::iter;
        let mut rng = crate::test::rng(805);

        // Test by generating a relatively large number of chars, so we also
        // take the rejection sampling path.
        let word: String = iter::repeat(())
            .map(|()| rng.gen::<char>())
            .take(1000)
            .collect();
        assert!(word.len() != 0);
    }

    #[test]
    fn test_alphanumeric() {
        let mut rng = crate::test::rng(806);

        // Test by generating a relatively large number of chars, so we also
        // take the rejection sampling path.
        let mut incorrect = false;
        for _ in 0..100 {
            let c = rng.sample(Alphanumeric);
            incorrect |= !((c >= '0' && c <= '9') ||
                           (c >= 'A' && c <= 'Z') ||
                           (c >= 'a' && c <= 'z') );
        }
        assert!(incorrect == false);
    }

    #[test]
    fn value_stability() {
        fn test_samples<T: Copy + core::fmt::Debug + PartialEq, D: Distribution<T>>(
            distr: &D, zero: T, expected: &[T],
        ) {
            let mut rng = crate::test::rng(807);
            let mut buf = [zero; 5];
            for x in &mut buf {
                *x = rng.sample(&distr);
            }
            assert_eq!(&buf, expected);
        }

        test_samples(&Standard, 'a', &[
            '\u{8cdac}',
            '\u{a346a}',
            '\u{80120}',
            '\u{ed692}',
            '\u{35888}',
        ]);
        test_samples(&Alphanumeric, 'a', &['h', 'm', 'e', '3', 'M']);
        test_samples(&Standard, false, &[true, true, false, true, false]);
        test_samples(&Standard, None as Option<bool>, &[
            Some(true),
            None,
            Some(false),
            None,
            Some(false),
        ]);
        test_samples(&Standard, Wrapping(0i32), &[
            Wrapping(-2074640887),
            Wrapping(-1719949321),
            Wrapping(2018088303),
            Wrapping(-547181756),
            Wrapping(838957336),
        ]);

        // We test only sub-sets of tuple and array impls
        test_samples(&Standard, (), &[(), (), (), (), ()]);
        test_samples(&Standard, (false,), &[
            (true,),
            (true,),
            (false,),
            (true,),
            (false,),
        ]);
        test_samples(&Standard, (false, false), &[
            (true, true),
            (false, true),
            (false, false),
            (true, false),
            (false, false),
        ]);

        test_samples(&Standard, [0u8; 0], &[[], [], [], [], []]);
        test_samples(&Standard, [0u8; 3], &[
            [9, 247, 111],
            [68, 24, 13],
            [174, 19, 194],
            [172, 69, 213],
            [149, 207, 29],
        ]);
    }
}
<|endoftext|>


<commit_before>//! The `event` module contains traits and structs to actually run your game mainloop
//! and handle top-level state, as well as handle input events such as keyboard
//! and mouse.
//!
//! If you don't want to do this, you can write your own mainloop and
//! get the necessary event machinery by calling
//! `context.sdl_context.event_pump()` on your `Context`.  You can
//! then call whatever SDL event methods you want on that.  This is
//! not particularly elegant and is not guaranteed to be stable across
//! different versions of ggez (for instance, we may someday get rid of SDL2),
//! but trying to wrap it
//! up more conveniently really ends up with the exact same interface.
//!
//! See the `eventloop` example for an implementation.

use sdl2;

/// A key code.
pub use sdl2::keyboard::Keycode;

/// A struct that holds the state of modifier buttons such as ctrl or shift.
pub use sdl2::keyboard::Mod;
/// A mouse button press.
pub use sdl2::mouse::MouseButton;
/// A struct containing the mouse state at a given instant.
pub use sdl2::mouse::MouseState;

/// A controller button.
pub use sdl2::controller::Button;
/// A controller axis.
pub use sdl2::controller::Axis;

/// The event iterator
pub use sdl2::event::EventPollIterator;
pub use sdl2::event::Event;

use sdl2::event::Event::*;
use sdl2::event;
use sdl2::mouse;
use sdl2::keyboard;

use context::Context;
use GameResult;

pub use sdl2::keyboard::{CAPSMOD, LALTMOD, LCTRLMOD, LGUIMOD, LSHIFTMOD, MODEMOD, NOMOD, NUMMOD,
                         RALTMOD, RCTRLMOD, RESERVEDMOD, RGUIMOD, RSHIFTMOD};

/// A trait defining event callbacks; your primary interface with
/// `ggez`'s event loop.  Have a type implement this trait and
/// override at least the update() and draw() methods, then pass it to
/// `event::run()` to run the game's mainloop.
///
/// The default event handlers do nothing, apart from
/// `key_down_event()`, which will by default exit the game if escape
/// is pressed.  Just override the methods you want to do things with.
pub trait EventHandler {
    /// Called upon each physics update to the game.
    /// This should be where the game's logic takes place.
    fn update(&mut self, _ctx: &mut Context) -> GameResult<()>;

    /// Called to do the drawing of your game.
    /// You probably want to start this with
    /// `graphics::clear()` and end it with
    /// `graphics::present()` and `timer::yield_now()`
    fn draw(&mut self, _ctx: &mut Context) -> GameResult<()>;

    /// A mouse button was pressed
    fn mouse_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _button: mouse::MouseButton,
        _x: i32,
        _y: i32,
    ) {
    }

    /// A mouse button was released
    fn mouse_button_up_event(
        &mut self,
        _ctx: &mut Context,
        _button: mouse::MouseButton,
        _x: i32,
        _y: i32,
    ) {
    }

    /// The mouse was moved; it provides both absolute x and y coordinates in the window,
    /// and relative x and y coordinates compared to its last position.
    fn mouse_motion_event(
        &mut self,
        _ctx: &mut Context,
        _state: mouse::MouseState,
        _x: i32,
        _y: i32,
        _xrel: i32,
        _yrel: i32,
    ) {
    }

    /// The mousewheel was scrolled, vertically (y, positive away from and negative toward the user)
    /// or horizontally (x, positive to the right and negative to the left).
    fn mouse_wheel_event(&mut self, _ctx: &mut Context, _x: i32, _y: i32) {}

    /// A keyboard button was pressed.
    fn key_down_event(&mut self, ctx: &mut Context, keycode: Keycode, _keymod: Mod, _repeat: bool) {
        if keycode == keyboard::Keycode::Escape {
            ctx.quit().expect("Should never fail");
        }
    }

    /// A keyboard button was released.
    fn key_up_event(&mut self, _ctx: &mut Context, _keycode: Keycode, _keymod: Mod, _repeat: bool) {
    }

    /// Candidate text is passed by the OS (via Input Method Editor).
    /// Refer to:
    /// <https://wiki.libsdl.org/SDL_TextEditingEvent>
    /// <https://wiki.libsdl.org/SDL_TextInputEvent>
    /// <https://wiki.libsdl.org/Tutorials/TextInput>
    fn text_editing_event(&mut self, _ctx: &mut Context, _text: String, _start: i32, _length: i32) {

    }

    /// Resulting text (usually a unicode character) is passed by the OS (via Input Method Editor).
    /// Refer to:
    /// <https://wiki.libsdl.org/SDL_TextEditingEvent>
    /// <https://wiki.libsdl.org/SDL_TextInputEvent>
    /// <https://wiki.libsdl.org/Tutorials/TextInput>
    fn text_input_event(&mut self, _ctx: &mut Context, _text: String) {}

    /// A controller button was pressed; instance_id identifies which controller.
    fn controller_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _btn: Button,
        _instance_id: i32,
    ) {
    }
    /// A controller button was released.
    fn controller_button_up_event(&mut self, _ctx: &mut Context, _btn: Button, _instance_id: i32) {}
    /// A controller axis moved.
    fn controller_axis_event(
        &mut self,
        _ctx: &mut Context,
        _axis: Axis,
        _value: i16,
        _instance_id: i32,
    ) {
    }

    /// Called when the window is shown or hidden.
    fn focus_event(&mut self, _ctx: &mut Context, _gained: bool) {}

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self, _ctx: &mut Context) -> bool {
        println!("quit_event() callback called, quitting...");
        false
    }

    /// Called when the user resizes the window.
    /// Is not called when you resize it yourself with
    /// `graphics::set_mode()` though.
    fn resize_event(&mut self, _ctx: &mut Context, _width: u32, _height: u32) {}
}

/// A handle to access the OS's event pump.
pub struct Events(sdl2::EventPump);

use std::fmt;
impl fmt::Debug for Events {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<Events: {:p}>", self)
    }
}

impl Events {
    /// Create a new Events object.
    pub fn new(ctx: &Context) -> GameResult<Events> {
        let e = ctx.sdl_context.event_pump()?;
        Ok(Events(e))
    }

    /// Get an iterator for all events.
    pub fn poll(&mut self) -> EventPollIterator {
        self.0.poll_iter()
    }
}

/// Runs the game's main loop, calling event callbacks on the given state
/// object as events occur.
///
/// It does not try to do any type of framerate limiting.  See the
/// documentation for the `timer` module for more info.
pub fn run<S>(ctx: &mut Context, state: &mut S) -> GameResult<()>
where
    S: EventHandler,
{
    let mut event_pump = ctx.sdl_context.event_pump()?;

    let mut continuing = true;
    while continuing {
        ctx.timer_context.tick();

        for event in event_pump.poll_iter() {
            ctx.process_event(&event);
            match event {
                Quit { .. } => {
                    continuing = state.quit_event(ctx);
                    // println!("Quit event: {:?}", t);
                }
                KeyDown {
                    keycode,
                    keymod,
                    repeat,
                    ..
                } => {
                    if let Some(key) = keycode {
                        state.key_down_event(ctx, key, keymod, repeat)
                    }
                }
                KeyUp {
                    keycode,
                    keymod,
                    repeat,
                    ..
                } => {
                    if let Some(key) = keycode {
                        state.key_up_event(ctx, key, keymod, repeat)
                    }
                }
                TextEditing {
                    text,
                    start,
                    length,
                    ..
                } => state.text_editing_event(ctx, text, start, length),
                TextInput { text, .. } => state.text_input_event(ctx, text),
                MouseButtonDown {
                    mouse_btn, x, y, ..
                } => state.mouse_button_down_event(ctx, mouse_btn, x, y),
                MouseButtonUp {
                    mouse_btn, x, y, ..
                } => state.mouse_button_up_event(ctx, mouse_btn, x, y),
                MouseMotion {
                    mousestate,
                    x,
                    y,
                    xrel,
                    yrel,
                    ..
                } => {
                    state.mouse_motion_event(ctx, mousestate, x, y, xrel, yrel);
                }
                MouseWheel { x, y, .. } => state.mouse_wheel_event(ctx, x, y),
                ControllerButtonDown { button, which, .. } => {
                    state.controller_button_down_event(ctx, button, which)
                }
                ControllerButtonUp { button, which, .. } => {
                    state.controller_button_up_event(ctx, button, which)
                }
                ControllerAxisMotion {
                    axis, value, which, ..
                } => state.controller_axis_event(ctx, axis, value, which),
                Window {
                    win_event: event::WindowEvent::FocusGained,
                    ..
                } => state.focus_event(ctx, true),
                Window {
                    win_event: event::WindowEvent::FocusLost,
                    ..
                } => state.focus_event(ctx, false),
                Window {
                    win_event: event::WindowEvent::Resized(w, h),
                    ..
                } => {
                    state.resize_event(ctx, w as u32, h as u32);
                }
                _ => {}
            }
        }
        state.update(ctx)?;
        state.draw(ctx)?;
    }

    Ok(())
}
<commit_msg>Changed `EventHandler::quit_event()` to use `debug!`<commit_after>//! The `event` module contains traits and structs to actually run your game mainloop
//! and handle top-level state, as well as handle input events such as keyboard
//! and mouse.
//!
//! If you don't want to do this, you can write your own mainloop and
//! get the necessary event machinery by calling
//! `context.sdl_context.event_pump()` on your `Context`.  You can
//! then call whatever SDL event methods you want on that.  This is
//! not particularly elegant and is not guaranteed to be stable across
//! different versions of ggez (for instance, we may someday get rid of SDL2),
//! but trying to wrap it
//! up more conveniently really ends up with the exact same interface.
//!
//! See the `eventloop` example for an implementation.

use sdl2;

/// A key code.
pub use sdl2::keyboard::Keycode;

/// A struct that holds the state of modifier buttons such as ctrl or shift.
pub use sdl2::keyboard::Mod;
/// A mouse button press.
pub use sdl2::mouse::MouseButton;
/// A struct containing the mouse state at a given instant.
pub use sdl2::mouse::MouseState;

/// A controller button.
pub use sdl2::controller::Button;
/// A controller axis.
pub use sdl2::controller::Axis;

/// The event iterator
pub use sdl2::event::EventPollIterator;
pub use sdl2::event::Event;

use sdl2::event::Event::*;
use sdl2::event;
use sdl2::mouse;
use sdl2::keyboard;

use context::Context;
use GameResult;

pub use sdl2::keyboard::{CAPSMOD, LALTMOD, LCTRLMOD, LGUIMOD, LSHIFTMOD, MODEMOD, NOMOD, NUMMOD,
                         RALTMOD, RCTRLMOD, RESERVEDMOD, RGUIMOD, RSHIFTMOD};

/// A trait defining event callbacks; your primary interface with
/// `ggez`'s event loop.  Have a type implement this trait and
/// override at least the update() and draw() methods, then pass it to
/// `event::run()` to run the game's mainloop.
///
/// The default event handlers do nothing, apart from
/// `key_down_event()`, which will by default exit the game if escape
/// is pressed.  Just override the methods you want to do things with.
pub trait EventHandler {
    /// Called upon each physics update to the game.
    /// This should be where the game's logic takes place.
    fn update(&mut self, _ctx: &mut Context) -> GameResult<()>;

    /// Called to do the drawing of your game.
    /// You probably want to start this with
    /// `graphics::clear()` and end it with
    /// `graphics::present()` and `timer::yield_now()`
    fn draw(&mut self, _ctx: &mut Context) -> GameResult<()>;

    /// A mouse button was pressed
    fn mouse_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _button: mouse::MouseButton,
        _x: i32,
        _y: i32,
    ) {
    }

    /// A mouse button was released
    fn mouse_button_up_event(
        &mut self,
        _ctx: &mut Context,
        _button: mouse::MouseButton,
        _x: i32,
        _y: i32,
    ) {
    }

    /// The mouse was moved; it provides both absolute x and y coordinates in the window,
    /// and relative x and y coordinates compared to its last position.
    fn mouse_motion_event(
        &mut self,
        _ctx: &mut Context,
        _state: mouse::MouseState,
        _x: i32,
        _y: i32,
        _xrel: i32,
        _yrel: i32,
    ) {
    }

    /// The mousewheel was scrolled, vertically (y, positive away from and negative toward the user)
    /// or horizontally (x, positive to the right and negative to the left).
    fn mouse_wheel_event(&mut self, _ctx: &mut Context, _x: i32, _y: i32) {}

    /// A keyboard button was pressed.
    fn key_down_event(&mut self, ctx: &mut Context, keycode: Keycode, _keymod: Mod, _repeat: bool) {
        if keycode == keyboard::Keycode::Escape {
            ctx.quit().expect("Should never fail");
        }
    }

    /// A keyboard button was released.
    fn key_up_event(&mut self, _ctx: &mut Context, _keycode: Keycode, _keymod: Mod, _repeat: bool) {
    }

    /// Candidate text is passed by the OS (via Input Method Editor).
    /// Refer to:
    /// <https://wiki.libsdl.org/SDL_TextEditingEvent>
    /// <https://wiki.libsdl.org/SDL_TextInputEvent>
    /// <https://wiki.libsdl.org/Tutorials/TextInput>
    fn text_editing_event(&mut self, _ctx: &mut Context, _text: String, _start: i32, _length: i32) {

    }

    /// Resulting text (usually a unicode character) is passed by the OS (via Input Method Editor).
    /// Refer to:
    /// <https://wiki.libsdl.org/SDL_TextEditingEvent>
    /// <https://wiki.libsdl.org/SDL_TextInputEvent>
    /// <https://wiki.libsdl.org/Tutorials/TextInput>
    fn text_input_event(&mut self, _ctx: &mut Context, _text: String) {}

    /// A controller button was pressed; instance_id identifies which controller.
    fn controller_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _btn: Button,
        _instance_id: i32,
    ) {
    }
    /// A controller button was released.
    fn controller_button_up_event(&mut self, _ctx: &mut Context, _btn: Button, _instance_id: i32) {}
    /// A controller axis moved.
    fn controller_axis_event(
        &mut self,
        _ctx: &mut Context,
        _axis: Axis,
        _value: i16,
        _instance_id: i32,
    ) {
    }

    /// Called when the window is shown or hidden.
    fn focus_event(&mut self, _ctx: &mut Context, _gained: bool) {}

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self, _ctx: &mut Context) -> bool {
        debug!("quit_event() callback called, quitting...");
        false
    }

    /// Called when the user resizes the window.
    /// Is not called when you resize it yourself with
    /// `graphics::set_mode()` though.
    fn resize_event(&mut self, _ctx: &mut Context, _width: u32, _height: u32) {}
}

/// A handle to access the OS's event pump.
pub struct Events(sdl2::EventPump);

use std::fmt;
impl fmt::Debug for Events {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<Events: {:p}>", self)
    }
}

impl Events {
    /// Create a new Events object.
    pub fn new(ctx: &Context) -> GameResult<Events> {
        let e = ctx.sdl_context.event_pump()?;
        Ok(Events(e))
    }

    /// Get an iterator for all events.
    pub fn poll(&mut self) -> EventPollIterator {
        self.0.poll_iter()
    }
}

/// Runs the game's main loop, calling event callbacks on the given state
/// object as events occur.
///
/// It does not try to do any type of framerate limiting.  See the
/// documentation for the `timer` module for more info.
pub fn run<S>(ctx: &mut Context, state: &mut S) -> GameResult<()>
where
    S: EventHandler,
{
    let mut event_pump = ctx.sdl_context.event_pump()?;

    let mut continuing = true;
    while continuing {
        ctx.timer_context.tick();

        for event in event_pump.poll_iter() {
            ctx.process_event(&event);
            match event {
                Quit { .. } => {
                    continuing = state.quit_event(ctx);
                    // println!("Quit event: {:?}", t);
                }
                KeyDown {
                    keycode,
                    keymod,
                    repeat,
                    ..
                } => {
                    if let Some(key) = keycode {
                        state.key_down_event(ctx, key, keymod, repeat)
                    }
                }
                KeyUp {
                    keycode,
                    keymod,
                    repeat,
                    ..
                } => {
                    if let Some(key) = keycode {
                        state.key_up_event(ctx, key, keymod, repeat)
                    }
                }
                TextEditing {
                    text,
                    start,
                    length,
                    ..
                } => state.text_editing_event(ctx, text, start, length),
                TextInput { text, .. } => state.text_input_event(ctx, text),
                MouseButtonDown {
                    mouse_btn, x, y, ..
                } => state.mouse_button_down_event(ctx, mouse_btn, x, y),
                MouseButtonUp {
                    mouse_btn, x, y, ..
                } => state.mouse_button_up_event(ctx, mouse_btn, x, y),
                MouseMotion {
                    mousestate,
                    x,
                    y,
                    xrel,
                    yrel,
                    ..
                } => {
                    state.mouse_motion_event(ctx, mousestate, x, y, xrel, yrel);
                }
                MouseWheel { x, y, .. } => state.mouse_wheel_event(ctx, x, y),
                ControllerButtonDown { button, which, .. } => {
                    state.controller_button_down_event(ctx, button, which)
                }
                ControllerButtonUp { button, which, .. } => {
                    state.controller_button_up_event(ctx, button, which)
                }
                ControllerAxisMotion {
                    axis, value, which, ..
                } => state.controller_axis_event(ctx, axis, value, which),
                Window {
                    win_event: event::WindowEvent::FocusGained,
                    ..
                } => state.focus_event(ctx, true),
                Window {
                    win_event: event::WindowEvent::FocusLost,
                    ..
                } => state.focus_event(ctx, false),
                Window {
                    win_event: event::WindowEvent::Resized(w, h),
                    ..
                } => {
                    state.resize_event(ctx, w as u32, h as u32);
                }
                _ => {}
            }
        }
        state.update(ctx)?;
        state.draw(ctx)?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>bitflags::bitflags! {
    /// Distribution flags.
    pub struct DistributionFlags: u64 {
        /// The node is to be published and part of the global namespace.
        const PUBLISHED = 0x01;

        /// The node implements an atom cache (obsolete).
        const ATOM_CACHE = 0x02;

        /// The node implements extended (3 × 32 bits) references (required).
        ///
        /// [NOTE] This flag is mandatory. If not present, the connection is refused.
        const EXTENDED_REFERENCES = 0x04;

        /// The node implements distributed process monitoring.
        ///
        /// [NOTE] This flag will become mandatory in OTP 25.
        const DIST_MONITOR = 0x08;

        /// The node uses separate tag for funs (lambdas) in the distribution protocol.
        const FUN_TAGS = 0x10;

        /// The node implements distributed named process monitoring.
        const DIST_MONITOR_NAME = 0x20;

        /// The (hidden) node implements atom cache (obsolete).
        const HIDDEN_ATOM_CACHE = 0x40;

        /// The node understands new fun tags.
        ///
        /// [NOTE] This flag is mandatory. If not present, the connection is refused.
        const NEW_FUN_TAGS = 0x80;

        /// The node can handle extended pids and ports (required).
        ///
        /// [NOTE] This flag is mandatory. If not present, the connection is refused.
        const EXTENDED_PIDS_PORTS = 0x100;

        /// This node understands `EXPORT_EXT` tag.
        ///
        /// [NOTE] This flag will become mandatory in OTP 25.
        const EXPORT_PTR_TAG = 0x200;

        /// The node understands bit binaries.
        ///
        /// [NOTE] This flag will become mandatory in OTP 25.
        const BIT_BINARIES = 0x400;

        /// The node understandss new float format.
        ///
        /// [NOTE] This flag will become mandatory in OTP 25.
        const NEW_FLOATS = 0x800;

        /// This node allows unicode characters in I/O operations.
        const UNICODE_IO = 0x1000;

        /// The node implements atom cache in distribution header.
        ///
        /// Note that currently `erl_dist` can not handle distribution headers.
        const DIST_HDR_ATOM_CACHE = 0x2000;

        /// The node understands the `SMALL_ATOM_EXT` tag.
        const SMALL_ATOM_TAGS = 0x4000;

        /// The node understands UTF-8 encoded atoms.
        ///
        /// [NOTE] This flag is mandatory. If not present, the connection is refused.
        const UTF8_ATOMS = 0x10000;

        /// The node understands maps.
        ///
        /// [NOTE] This flag will become mandatory in OTP 25.
        const MAP_TAGS = 0x20000;

        /// The node understands big node creation tags `NEW_PID_EXT`, `NEW_PORT_EXT` and `NEWER_REFERENCE_EXT`.
        ///
        /// [NOTE] This flag is mandatory. If not present, the connection is refused.
        const BIG_CREATION = 0x40000;

        /// Use the `SEND_SENDER` control message instead of the `SEND` control message and use the `SEND_SENDER_TT` control message instead of the `SEND_TT` control message.
        const SEND_SENDER = 0x80000;

        /// The node understands any term as the seqtrace label.
        const BIG_SEQTRACE_LABELS = 0x100000;

        /// Use the `PAYLOAD_EXIT`, `PAYLOAD_EXIT_TT`, `PAYLOAD_EXIT2`, `PAYLOAD_EXIT2_TT` and `PAYLOAD_MONITOR_P_EXIT` control messages instead of the non-PAYLOAD variants.
        const EXIT_PAYLOAD = 0x400000;

        /// Use fragmented distribution messages to send large messages.
        const FRAGMENTS = 0x800000;

        /// The node supports the new connection setup handshake (version 6) introduced in OTP 23.
        const HANDSHAKE_23 = 0x1000000;

        /// Use the new link protocol.
        ///
        /// Unless both nodes have set the `UNLINK_ID` flag, the old link protocol will be used as a fallback.
        ///
        /// [NOTE] This flag will become mandatory in OTP 25.
        const UNLINK_ID = 0x2000000;

        /// Set if the `SPAWN_REQUEST`, `SPAWN_REQUEST_TT`, `SPAWN_REPLY`, `SPAWN_REPLY_TT` control messages are supported.
        const SPAWN = 1 << 32;

        /// Dynamic node name.
        ///
        /// This is not a capability but rather used as a request from the connecting node
        /// to receive its node name from the accepting node as part of the handshake.
        const NAME_ME = 1 << 33;

        /// The node accepts a larger amount of data in pids, ports and references (node container types version 4).
        ///
        /// In the pid case full 32-bit `ID` and `Serial` fields in `NEW_PID_EXT`,
        /// in the port case a 64-bit integer in `V4_PORT_EXT`, and in the reference case up to 5 32-bit ID words are
        /// now accepted in `NEWER_REFERENCE_EXT`.
        /// Introduced in OTP 24.
        ///
        /// [NOTE] This flag will become mandatory in OTP 26.
        const V4_NC = 1 << 34;

        /// The node supports process alias and can by this handle the `ALIAS_SEND` and `ALIAS_SEND_TT` control messages.
        ///
        /// Introduced in OTP 24.
        const ALIAS = 1 << 35;
    }
}

impl Default for DistributionFlags {
    // TODO: update
    /// The default distribution flags.
    ///
    /// This is equivalent to the following code:
    ///
    /// ```no_run
    /// # use erl_dist::DistributionFlags;
    /// DistributionFlags::EXTENDED_REFERENCES | DistributionFlags::EXTENDED_PIDS_PORTS |
    /// DistributionFlags::FUN_TAGS | DistributionFlags::NEW_FUN_TAGS |
    /// DistributionFlags::EXPORT_PTR_TAG | DistributionFlags::BIT_BINARIES |
    /// DistributionFlags::NEW_FLOATS | DistributionFlags::SMALL_ATOM_TAGS |
    /// DistributionFlags::UTF8_ATOMS | DistributionFlags::MAP_TAGS
    /// # ;
    /// ```
    fn default() -> Self {
        Self::EXTENDED_REFERENCES
            | Self::EXTENDED_PIDS_PORTS
            | Self::FUN_TAGS
            | Self::NEW_FUN_TAGS
            | Self::EXPORT_PTR_TAG
            | Self::BIT_BINARIES
            | Self::NEW_FLOATS
            | Self::SMALL_ATOM_TAGS
            | Self::UTF8_ATOMS
            | Self::MAP_TAGS
            | Self::HANDSHAKE_23
            | Self::BIG_CREATION
    }
}

impl DistributionFlags {
    /// Gets the flags the this crate supports.
    ///
    /// This is the same as [`DistributionFlags::default()`].
    pub fn supported() -> Self {
        Self::EXTENDED_REFERENCES
            | Self::FUN_TAGS
            | Self::NEW_FUN_TAGS
            | Self::EXTENDED_PIDS_PORTS
            | Self::EXPORT_PTR_TAG
            | Self::BIT_BINARIES
            | Self::NEW_FLOATS
            | Self::UTF8_ATOMS
            | Self::MAP_TAGS
            | Self::BIG_CREATION
    }
}
<commit_msg>Update the default value of `DistributionFlags`<commit_after>bitflags::bitflags! {
    /// Distribution flags.
    pub struct DistributionFlags: u64 {
        /// The node is to be published and part of the global namespace.
        const PUBLISHED = 0x01;

        /// The node implements an atom cache (obsolete).
        const ATOM_CACHE = 0x02;

        /// The node implements extended (3 × 32 bits) references (required).
        ///
        /// [NOTE] This flag is mandatory. If not present, the connection is refused.
        const EXTENDED_REFERENCES = 0x04;

        /// The node implements distributed process monitoring.
        ///
        /// [NOTE] This flag will become mandatory in OTP 25.
        const DIST_MONITOR = 0x08;

        /// The node uses separate tag for funs (lambdas) in the distribution protocol.
        const FUN_TAGS = 0x10;

        /// The node implements distributed named process monitoring.
        const DIST_MONITOR_NAME = 0x20;

        /// The (hidden) node implements atom cache (obsolete).
        const HIDDEN_ATOM_CACHE = 0x40;

        /// The node understands new fun tags.
        ///
        /// [NOTE] This flag is mandatory. If not present, the connection is refused.
        const NEW_FUN_TAGS = 0x80;

        /// The node can handle extended pids and ports (required).
        ///
        /// [NOTE] This flag is mandatory. If not present, the connection is refused.
        const EXTENDED_PIDS_PORTS = 0x100;

        /// This node understands `EXPORT_EXT` tag.
        ///
        /// [NOTE] This flag will become mandatory in OTP 25.
        const EXPORT_PTR_TAG = 0x200;

        /// The node understands bit binaries.
        ///
        /// [NOTE] This flag will become mandatory in OTP 25.
        const BIT_BINARIES = 0x400;

        /// The node understandss new float format.
        ///
        /// [NOTE] This flag will become mandatory in OTP 25.
        const NEW_FLOATS = 0x800;

        /// This node allows unicode characters in I/O operations.
        const UNICODE_IO = 0x1000;

        /// The node implements atom cache in distribution header.
        ///
        /// Note that currently `erl_dist` can not handle distribution headers.
        const DIST_HDR_ATOM_CACHE = 0x2000;

        /// The node understands the `SMALL_ATOM_EXT` tag.
        const SMALL_ATOM_TAGS = 0x4000;

        /// The node understands UTF-8 encoded atoms.
        ///
        /// [NOTE] This flag is mandatory. If not present, the connection is refused.
        const UTF8_ATOMS = 0x10000;

        /// The node understands maps.
        ///
        /// [NOTE] This flag will become mandatory in OTP 25.
        const MAP_TAGS = 0x20000;

        /// The node understands big node creation tags `NEW_PID_EXT`, `NEW_PORT_EXT` and `NEWER_REFERENCE_EXT`.
        ///
        /// [NOTE] This flag is mandatory. If not present, the connection is refused.
        const BIG_CREATION = 0x40000;

        /// Use the `SEND_SENDER` control message instead of the `SEND` control message and use the `SEND_SENDER_TT` control message instead of the `SEND_TT` control message.
        const SEND_SENDER = 0x80000;

        /// The node understands any term as the seqtrace label.
        const BIG_SEQTRACE_LABELS = 0x100000;

        /// Use the `PAYLOAD_EXIT`, `PAYLOAD_EXIT_TT`, `PAYLOAD_EXIT2`, `PAYLOAD_EXIT2_TT` and `PAYLOAD_MONITOR_P_EXIT` control messages instead of the non-PAYLOAD variants.
        const EXIT_PAYLOAD = 0x400000;

        /// Use fragmented distribution messages to send large messages.
        const FRAGMENTS = 0x800000;

        /// The node supports the new connection setup handshake (version 6) introduced in OTP 23.
        const HANDSHAKE_23 = 0x1000000;

        /// Use the new link protocol.
        ///
        /// Unless both nodes have set the `UNLINK_ID` flag, the old link protocol will be used as a fallback.
        ///
        /// [NOTE] This flag will become mandatory in OTP 25.
        const UNLINK_ID = 0x2000000;

        /// Set if the `SPAWN_REQUEST`, `SPAWN_REQUEST_TT`, `SPAWN_REPLY`, `SPAWN_REPLY_TT` control messages are supported.
        const SPAWN = 1 << 32;

        /// Dynamic node name.
        ///
        /// This is not a capability but rather used as a request from the connecting node
        /// to receive its node name from the accepting node as part of the handshake.
        const NAME_ME = 1 << 33;

        /// The node accepts a larger amount of data in pids, ports and references (node container types version 4).
        ///
        /// In the pid case full 32-bit `ID` and `Serial` fields in `NEW_PID_EXT`,
        /// in the port case a 64-bit integer in `V4_PORT_EXT`, and in the reference case up to 5 32-bit ID words are
        /// now accepted in `NEWER_REFERENCE_EXT`.
        /// Introduced in OTP 24.
        ///
        /// [NOTE] This flag will become mandatory in OTP 26.
        const V4_NC = 1 << 34;

        /// The node supports process alias and can by this handle the `ALIAS_SEND` and `ALIAS_SEND_TT` control messages.
        ///
        /// Introduced in OTP 24.
        const ALIAS = 1 << 35;
    }
}

impl Default for DistributionFlags {
    fn default() -> Self {
        Self::new()
    }
}

impl DistributionFlags {
    /// Makes a new [`DistributionFlags`] with the default flags.
    ///
    /// This is equivalent to the following code:
    ///
    /// ```
    /// # use erl_dist::DistributionFlags;
    /// DistributionFlags::mandatory() | DistributionFlags::HANDSHAKE_23;
    /// ```
    pub fn new() -> Self {
        Self::mandatory() | Self::HANDSHAKE_23
    }

    /// Gets the mandatory flags (in OTP 25).
    pub fn mandatory() -> Self {
        Self::EXTENDED_REFERENCES
            | Self::FUN_TAGS
            | Self::NEW_FUN_TAGS
            | Self::EXTENDED_PIDS_PORTS
            | Self::EXPORT_PTR_TAG
            | Self::BIT_BINARIES
            | Self::NEW_FLOATS
            | Self::UTF8_ATOMS
            | Self::MAP_TAGS
            | Self::BIG_CREATION
    }
}
<|endoftext|>


<commit_before><commit_msg>fix test name<commit_after><|endoftext|>