<commit_before>#![feature(test)]
#![cfg_attr(all(feature="i128_support", feature="nightly"), allow(stable_features))] // stable since 2018-03-27
#![cfg_attr(all(feature="i128_support", feature="nightly"), feature(i128_type, i128))]

extern crate test;
extern crate rand;

const RAND_BENCH_N: u64 = 1000;

use std::mem::size_of;
use test::Bencher;

use rand::{Rng, FromEntropy};
use rand::rngs::SmallRng;
use rand::distributions::*;

macro_rules! distr_int {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = SmallRng::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0 as $ty;
                for _ in 0..::RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum = accum.wrapping_add(x);
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
        }
    }
}

macro_rules! distr_float {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = SmallRng::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0.0;
                for _ in 0..::RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum += x;
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
        }
    }
}

macro_rules! distr {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = SmallRng::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0u32;
                for _ in 0..::RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum = accum.wrapping_add(x as u32);
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
        }
    }
}

// uniform
distr_int!(distr_uniform_i8, i8, Uniform::new(20i8, 100));
distr_int!(distr_uniform_i16, i16, Uniform::new(-500i16, 2000));
distr_int!(distr_uniform_i32, i32, Uniform::new(-200_000_000i32, 800_000_000));
distr_int!(distr_uniform_i64, i64, Uniform::new(3i64, 123_456_789_123));
#[cfg(feature = "i128_support")]
distr_int!(distr_uniform_i128, i128, Uniform::new(-123_456_789_123i128, 123_456_789_123_456_789));

distr_float!(distr_uniform_f32, f32, Uniform::new(2.26f32, 2.319));
distr_float!(distr_uniform_f64, f64, Uniform::new(2.26f64, 2.319));

// standard
distr_int!(distr_standard_i8, i8, Standard);
distr_int!(distr_standard_i16, i16, Standard);
distr_int!(distr_standard_i32, i32, Standard);
distr_int!(distr_standard_i64, i64, Standard);
#[cfg(feature = "i128_support")]
distr_int!(distr_standard_i128, i128, Standard);

distr!(distr_standard_bool, bool, Standard);
distr!(distr_standard_alphanumeric, char, Alphanumeric);
distr!(distr_standard_codepoint, char, Standard);

distr_float!(distr_standard_f32, f32, Standard);
distr_float!(distr_standard_f64, f64, Standard);
distr_float!(distr_open01_f32, f32, Open01);
distr_float!(distr_open01_f64, f64, Open01);
distr_float!(distr_openclosed01_f32, f32, OpenClosed01);
distr_float!(distr_openclosed01_f64, f64, OpenClosed01);

// distributions
distr_float!(distr_exp, f64, Exp::new(1.23 * 4.56));
distr_float!(distr_normal, f64, Normal::new(-1.23, 4.56));
distr_float!(distr_log_normal, f64, LogNormal::new(-1.23, 4.56));
distr_float!(distr_gamma_large_shape, f64, Gamma::new(10., 1.0));
distr_float!(distr_gamma_small_shape, f64, Gamma::new(0.1, 1.0));
distr_float!(distr_cauchy, f64, Cauchy::new(4.2, 6.9));
distr_int!(distr_binomial, u64, Binomial::new(20, 0.7));
distr_int!(distr_poisson, u64, Poisson::new(4.0));
distr!(distr_bernoulli, bool, Bernoulli::new(0.18));

// Weighted
distr_int!(distr_weighted_i8, usize, WeightedIndex::new(&[1i8, 2, 3, 4, 12, 0, 2, 1]).unwrap());
distr_int!(distr_weighted_u32, usize, WeightedIndex::new(&[1u32, 2, 3, 4, 12, 0, 2, 1]).unwrap());
distr_int!(distr_weighted_f64, usize, WeightedIndex::new(&[1.0f64, 0.001, 1.0/3.0, 4.01, 0.0, 3.3, 22.0, 0.001]).unwrap());
distr_int!(distr_weighted_large_set, usize, WeightedIndex::new((0..10000).rev().chain(1..10001)).unwrap());

// construct and sample from a range
macro_rules! gen_range_int {
    ($fnn:ident, $ty:ident, $low:expr, $high:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = SmallRng::from_entropy();

            b.iter(|| {
                let mut high = $high;
                let mut accum: $ty = 0;
                for _ in 0..::RAND_BENCH_N {
                    accum = accum.wrapping_add(rng.gen_range($low, high));
                    // force recalculation of range each time
                    high = high.wrapping_add(1) & std::$ty::MAX;
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
        }
    }
}

gen_range_int!(gen_range_i8, i8, -20i8, 100);
gen_range_int!(gen_range_i16, i16, -500i16, 2000);
gen_range_int!(gen_range_i32, i32, -200_000_000i32, 800_000_000);
gen_range_int!(gen_range_i64, i64, 3i64, 123_456_789_123);
#[cfg(feature = "i128_support")]
gen_range_int!(gen_range_i128, i128, -12345678901234i128, 123_456_789_123_456_789);

// construct and sample from a floating-point range
macro_rules! gen_range_float {
    ($fnn:ident, $ty:ident, $low:expr, $high:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = SmallRng::from_entropy();

            b.iter(|| {
                let mut high = $high;
                let mut low = $low;
                let mut accum: $ty = 0.0;
                for _ in 0..::RAND_BENCH_N {
                    accum += rng.gen_range(low, high);
                    // force recalculation of range each time
                    low += 0.9;
                    high += 1.1;
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
        }
    }
}

gen_range_float!(gen_range_f32, f32, -20000.0f32, 100000.0);
gen_range_float!(gen_range_f64, f64, 123.456f64, 7890.12);

#[bench]
fn dist_iter(b: &mut Bencher) {
    let mut rng = SmallRng::from_entropy();
    let distr = Normal::new(-2.71828, 3.14159);
    let mut iter = distr.sample_iter(&mut rng);

    b.iter(|| {
        let mut accum = 0.0;
        for _ in 0..::RAND_BENCH_N {
            accum += iter.next().unwrap();
        }
        accum
    });
    b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
}
<commit_msg>Add uniform Duration benches<commit_after>#![feature(test)]
#![cfg_attr(all(feature="i128_support", feature="nightly"), allow(stable_features))] // stable since 2018-03-27
#![cfg_attr(all(feature="i128_support", feature="nightly"), feature(i128_type, i128))]

extern crate test;
extern crate rand;

const RAND_BENCH_N: u64 = 1000;

use std::mem::size_of;
use test::Bencher;
use std::time::Duration;

use rand::{Rng, FromEntropy};
use rand::rngs::SmallRng;
use rand::distributions::*;

macro_rules! distr_int {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = SmallRng::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0 as $ty;
                for _ in 0..::RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum = accum.wrapping_add(x);
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
        }
    }
}

macro_rules! distr_float {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = SmallRng::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0.0;
                for _ in 0..::RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum += x;
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
        }
    }
}

macro_rules! distr_duration {
    ($fnn:ident, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = SmallRng::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = Duration::new(0, 0);
                for _ in 0..::RAND_BENCH_N {
                    let x: Duration = distr.sample(&mut rng);
                    accum = accum.checked_add(x).unwrap_or(Duration::new(u64::max_value(), 999_999_999));
                }
                accum
            });
            b.bytes = size_of::<Duration>() as u64 * ::RAND_BENCH_N;
        }
    }
}

macro_rules! distr {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = SmallRng::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0u32;
                for _ in 0..::RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum = accum.wrapping_add(x as u32);
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
        }
    }
}

// uniform
distr_int!(distr_uniform_i8, i8, Uniform::new(20i8, 100));
distr_int!(distr_uniform_i16, i16, Uniform::new(-500i16, 2000));
distr_int!(distr_uniform_i32, i32, Uniform::new(-200_000_000i32, 800_000_000));
distr_int!(distr_uniform_i64, i64, Uniform::new(3i64, 123_456_789_123));
#[cfg(feature = "i128_support")]
distr_int!(distr_uniform_i128, i128, Uniform::new(-123_456_789_123i128, 123_456_789_123_456_789));

distr_float!(distr_uniform_f32, f32, Uniform::new(2.26f32, 2.319));
distr_float!(distr_uniform_f64, f64, Uniform::new(2.26f64, 2.319));

distr_duration!(distr_uniform_duration_largest, Uniform::new(Duration::new(0, 0), Duration::new(u64::max_value(), 999_999_999)));
distr_duration!(distr_uniform_duration_large, Uniform::new(Duration::new(0, 0), Duration::new(u64::max_value()/1000, 1_000_000_000/2)));
distr_duration!(distr_uniform_duration_one, Uniform::new(Duration::new(0, 0), Duration::new(1, 0)));
distr_duration!(distr_uniform_duration_variety, Uniform::new(Duration::new(10000, 423423), Duration::new(200000, 6969954)));

// standard
distr_int!(distr_standard_i8, i8, Standard);
distr_int!(distr_standard_i16, i16, Standard);
distr_int!(distr_standard_i32, i32, Standard);
distr_int!(distr_standard_i64, i64, Standard);
#[cfg(feature = "i128_support")]
distr_int!(distr_standard_i128, i128, Standard);

distr!(distr_standard_bool, bool, Standard);
distr!(distr_standard_alphanumeric, char, Alphanumeric);
distr!(distr_standard_codepoint, char, Standard);

distr_float!(distr_standard_f32, f32, Standard);
distr_float!(distr_standard_f64, f64, Standard);
distr_float!(distr_open01_f32, f32, Open01);
distr_float!(distr_open01_f64, f64, Open01);
distr_float!(distr_openclosed01_f32, f32, OpenClosed01);
distr_float!(distr_openclosed01_f64, f64, OpenClosed01);

// distributions
distr_float!(distr_exp, f64, Exp::new(1.23 * 4.56));
distr_float!(distr_normal, f64, Normal::new(-1.23, 4.56));
distr_float!(distr_log_normal, f64, LogNormal::new(-1.23, 4.56));
distr_float!(distr_gamma_large_shape, f64, Gamma::new(10., 1.0));
distr_float!(distr_gamma_small_shape, f64, Gamma::new(0.1, 1.0));
distr_float!(distr_cauchy, f64, Cauchy::new(4.2, 6.9));
distr_int!(distr_binomial, u64, Binomial::new(20, 0.7));
distr_int!(distr_poisson, u64, Poisson::new(4.0));
distr!(distr_bernoulli, bool, Bernoulli::new(0.18));

// Weighted
distr_int!(distr_weighted_i8, usize, WeightedIndex::new(&[1i8, 2, 3, 4, 12, 0, 2, 1]).unwrap());
distr_int!(distr_weighted_u32, usize, WeightedIndex::new(&[1u32, 2, 3, 4, 12, 0, 2, 1]).unwrap());
distr_int!(distr_weighted_f64, usize, WeightedIndex::new(&[1.0f64, 0.001, 1.0/3.0, 4.01, 0.0, 3.3, 22.0, 0.001]).unwrap());
distr_int!(distr_weighted_large_set, usize, WeightedIndex::new((0..10000).rev().chain(1..10001)).unwrap());

// construct and sample from a range
macro_rules! gen_range_int {
    ($fnn:ident, $ty:ident, $low:expr, $high:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = SmallRng::from_entropy();

            b.iter(|| {
                let mut high = $high;
                let mut accum: $ty = 0;
                for _ in 0..::RAND_BENCH_N {
                    accum = accum.wrapping_add(rng.gen_range($low, high));
                    // force recalculation of range each time
                    high = high.wrapping_add(1) & std::$ty::MAX;
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
        }
    }
}

gen_range_int!(gen_range_i8, i8, -20i8, 100);
gen_range_int!(gen_range_i16, i16, -500i16, 2000);
gen_range_int!(gen_range_i32, i32, -200_000_000i32, 800_000_000);
gen_range_int!(gen_range_i64, i64, 3i64, 123_456_789_123);
#[cfg(feature = "i128_support")]
gen_range_int!(gen_range_i128, i128, -12345678901234i128, 123_456_789_123_456_789);

// construct and sample from a floating-point range
macro_rules! gen_range_float {
    ($fnn:ident, $ty:ident, $low:expr, $high:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = SmallRng::from_entropy();

            b.iter(|| {
                let mut high = $high;
                let mut low = $low;
                let mut accum: $ty = 0.0;
                for _ in 0..::RAND_BENCH_N {
                    accum += rng.gen_range(low, high);
                    // force recalculation of range each time
                    low += 0.9;
                    high += 1.1;
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
        }
    }
}

gen_range_float!(gen_range_f32, f32, -20000.0f32, 100000.0);
gen_range_float!(gen_range_f64, f64, 123.456f64, 7890.12);

#[bench]
fn dist_iter(b: &mut Bencher) {
    let mut rng = SmallRng::from_entropy();
    let distr = Normal::new(-2.71828, 3.14159);
    let mut iter = distr.sample_iter(&mut rng);

    b.iter(|| {
        let mut accum = 0.0;
        for _ in 0..::RAND_BENCH_N {
            accum += iter.next().unwrap();
        }
        accum
    });
    b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
}
<|endoftext|>


<commit_before>//! Definition of the `JoinAll` combinator, waiting for all of a list of futures
//! to finish.

use std::prelude::v1::*;

use std::fmt;
use std::mem;

use {Future, IntoFuture, Poll, Async};

#[derive(Debug)]
enum ElemState<T> where T: Future {
    Pending(T),
    Done(T::Item),
}

/// A future which takes a list of futures and resolves with a vector of the
/// completed values.
///
/// This future is created with the `join_all` method.
#[must_use = "futures do nothing unless polled"]
pub struct JoinAll<Item>
    where Item: IntoFuture,
{
    elems: Vec<ElemState<<Item as IntoFuture>::Future>>,
}

impl<I> fmt::Debug for JoinAll<I>
    where I: IntoIterator,
          I::Item: IntoFuture,
          <<I as IntoIterator>::Item as IntoFuture>::Future: fmt::Debug,
          <<I as IntoIterator>::Item as IntoFuture>::Item: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("JoinAll")
            .field("elems", &self.elems)
            .finish()
    }
}

/// Creates a future which represents a collection of the results of the futures
/// given.
///
/// The returned future will drive execution for all of its underlying futures,
/// collecting the results into a destination `Vec<T>` in the same order as they
/// were provided. If any future returns an error then all other futures will be
/// canceled and an error will be returned immediately. If all futures complete
/// successfully, however, then the returned future will succeed with a `Vec` of
/// all the successful results.
///
/// # Examples
///
/// ```
/// use futures::future::*;
///
/// let f = join_all(vec![
///     ok::<u32, u32>(1),
///     ok::<u32, u32>(2),
///     ok::<u32, u32>(3),
/// ]);
/// let f = f.map(|x| {
///     assert_eq!(x, [1, 2, 3]);
/// });
///
/// let f = join_all(vec![
///     Box::new(ok::<u32, u32>(1)),
///     Box::new(err::<u32, u32>(2)),
///     Box::new(ok::<u32, u32>(3)),
/// ]);
/// let f = f.then(|x| {
///     assert_eq!(x, Err(2));
///     x
/// });
/// ```
pub fn join_all<I>(i: I) -> JoinAll<I::Item>
    where I: IntoIterator,
          I::Item: IntoFuture,
{
    let elems = i.into_iter().map(|f| {
        ElemState::Pending(f.into_future())
    }).collect();
    JoinAll { elems: elems }
}

impl<Item> Future for JoinAll<Item>
    where Item: IntoFuture,
{
    type Item = Vec<<Item as IntoFuture>::Item>;
    type Error = <Item as IntoFuture>::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut all_done = true;

        for idx in 0 .. self.elems.len() {
            let done_val = match self.elems[idx] {
                ElemState::Pending(ref mut t) => {
                    match t.poll() {
                        Ok(Async::Ready(v)) => Ok(v),
                        Ok(Async::NotReady) => {
                            all_done = false;
                            continue
                        }
                        Err(e) => Err(e),
                    }
                }
                ElemState::Done(ref mut _v) => continue,
            };

            match done_val {
                Ok(v) => self.elems[idx] = ElemState::Done(v),
                Err(e) => {
                    // On completion drop all our associated resources
                    // ASAP.
                    self.elems = Vec::new();
                    return Err(e)
                }
            }
        }

        if all_done {
            let elems = mem::replace(&mut self.elems, Vec::new());
            let result = elems.into_iter().map(|e| {
                match e {
                    ElemState::Done(t) => t,
                    _ => unreachable!(),
                }
            }).collect();
            Ok(Async::Ready(result))
        } else {
            Ok(Async::NotReady)
        }
    }
}
<commit_msg>Fix Debug bounds.<commit_after>//! Definition of the `JoinAll` combinator, waiting for all of a list of futures
//! to finish.

use std::prelude::v1::*;

use std::fmt;
use std::mem;

use {Future, IntoFuture, Poll, Async};

#[derive(Debug)]
enum ElemState<T> where T: Future {
    Pending(T),
    Done(T::Item),
}

/// A future which takes a list of futures and resolves with a vector of the
/// completed values.
///
/// This future is created with the `join_all` method.
#[must_use = "futures do nothing unless polled"]
pub struct JoinAll<Item>
    where Item: IntoFuture,
{
    elems: Vec<ElemState<<Item as IntoFuture>::Future>>,
}

impl<I> fmt::Debug for JoinAll<I>
    where I: IntoFuture,
          <I as IntoFuture>::Future: fmt::Debug,
          <I as IntoFuture>::Item: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("JoinAll")
            .field("elems", &self.elems)
            .finish()
    }
}

/// Creates a future which represents a collection of the results of the futures
/// given.
///
/// The returned future will drive execution for all of its underlying futures,
/// collecting the results into a destination `Vec<T>` in the same order as they
/// were provided. If any future returns an error then all other futures will be
/// canceled and an error will be returned immediately. If all futures complete
/// successfully, however, then the returned future will succeed with a `Vec` of
/// all the successful results.
///
/// # Examples
///
/// ```
/// use futures::future::*;
///
/// let f = join_all(vec![
///     ok::<u32, u32>(1),
///     ok::<u32, u32>(2),
///     ok::<u32, u32>(3),
/// ]);
/// let f = f.map(|x| {
///     assert_eq!(x, [1, 2, 3]);
/// });
///
/// let f = join_all(vec![
///     Box::new(ok::<u32, u32>(1)),
///     Box::new(err::<u32, u32>(2)),
///     Box::new(ok::<u32, u32>(3)),
/// ]);
/// let f = f.then(|x| {
///     assert_eq!(x, Err(2));
///     x
/// });
/// ```
pub fn join_all<I>(i: I) -> JoinAll<I::Item>
    where I: IntoIterator,
          I::Item: IntoFuture,
{
    let elems = i.into_iter().map(|f| {
        ElemState::Pending(f.into_future())
    }).collect();
    JoinAll { elems: elems }
}

impl<Item> Future for JoinAll<Item>
    where Item: IntoFuture,
{
    type Item = Vec<<Item as IntoFuture>::Item>;
    type Error = <Item as IntoFuture>::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut all_done = true;

        for idx in 0 .. self.elems.len() {
            let done_val = match self.elems[idx] {
                ElemState::Pending(ref mut t) => {
                    match t.poll() {
                        Ok(Async::Ready(v)) => Ok(v),
                        Ok(Async::NotReady) => {
                            all_done = false;
                            continue
                        }
                        Err(e) => Err(e),
                    }
                }
                ElemState::Done(ref mut _v) => continue,
            };

            match done_val {
                Ok(v) => self.elems[idx] = ElemState::Done(v),
                Err(e) => {
                    // On completion drop all our associated resources
                    // ASAP.
                    self.elems = Vec::new();
                    return Err(e)
                }
            }
        }

        if all_done {
            let elems = mem::replace(&mut self.elems, Vec::new());
            let result = elems.into_iter().map(|e| {
                match e {
                    ElemState::Done(t) => t,
                    _ => unreachable!(),
                }
            }).collect();
            Ok(Async::Ready(result))
        } else {
            Ok(Async::NotReady)
        }
    }
}
<|endoftext|>


<commit_before>// TODO: COPYRIGHT, USE & AUTHORS
use super::ga_core::GASolution;
use super::ga_population::{GAPopulation, GAPopulationSortBasis};
use super::ga_random;

/// Selector Trait
///
/// Interface to Selection Schemes
pub trait GASelector<'a, T: GASolution>
{
    /// Assign the population on which to operate
    fn assign(&mut self, population: &'a mut GAPopulation<T>);
    /// Update internal state.
    /// Some selectors implement an empty update().
    fn update(&mut self) {}

    fn select(&mut self) -> &T;
}

pub trait GAScoreTypeBasedSelection<T: GASolution>
{
    fn score(&self, individual: &T) -> f32;

    fn population_sort_basis(&self) -> GAPopulationSortBasis;
}

pub struct GARawScoreBasedSelection;

impl<T: GASolution> GAScoreTypeBasedSelection<T> for GARawScoreBasedSelection
{
    fn score(&self, individual: &T) -> f32
    {
        individual.score()
    }

    fn population_sort_basis(&self) -> GAPopulationSortBasis
    {
        GAPopulationSortBasis::Raw
    }
}

pub struct GAScaledScoreBasedSelection;

impl<T: GASolution> GAScoreTypeBasedSelection<T> for GAScaledScoreBasedSelection
{
    fn score(&self, individual: &T) -> f32
    {
        individual.fitness()
    }

    fn population_sort_basis(&self) -> GAPopulationSortBasis
    {
        GAPopulationSortBasis::Scaled
    }
}

// GASolution-s live as long as the population. Lifetime 'a is bound to the
// population borrowed by the 'population' member, as well as to the enclosed
// GASolution-s, because they share the same memory.
pub struct GARankSelector<'a, T: 'a + GASolution>
{
    // Q: How to make this member common to all GASelectors?
    // Q: Will 'mut' make things more complex? When the rank selector is in
    //    scope and borrowing the population, no other objects will be able
    //    to borrow it, not even in non-mut mode according to the rules.
    // Selectors modify populations (they sort them, for instance), so the
    // reference must be 'mut'.
    population: &'a mut GAPopulation<T>,

    // TODO: Check correct lifetime.
    score_type_selection: &'a GAScoreTypeBasedSelection<T>
}

impl<'a, T: GASolution> GARankSelector<'a, T>
{
    pub fn new(p: &'a mut GAPopulation<T>, s: &'a GAScoreTypeBasedSelection<T>) -> GARankSelector<'a, T>
    {
        GARankSelector
        {
            population: p,
            score_type_selection: s
        }
    }
}

// TODO: DOC.
impl<'a, T: GASolution> GASelector<'a, T> for GARankSelector<'a, T>
{
    fn assign(&mut self, population: &'a mut GAPopulation<T>)
    {
        self.population = population;
    }

    fn select(&mut self) -> &T
    {
        // TODO: Confirm assumption that population has 1 individual at least.
        // Number of individuals that share best score.
        let mut best_count = 1;

        self.population.sort();

        // TODO: Use best() when implemented.
        // Q: Should individual() (ith_best()) return an optional or
        //    does it guarantee that it will always return something valid?
        //    What if the population is still empty?
        let best_score: f32 = self.score_type_selection.score(self.population.individual(0, self.score_type_selection.population_sort_basis()));

        // Skip 0th best.
        for i in 1..self.population.size()
        {
            if self.score_type_selection.score(self.population.individual(i, self.score_type_selection.population_sort_basis())) != best_score
            {
                break;
            }

            best_count = best_count + 1;
        }

        // Select any individual from those that share best score.
        self.population.individual(ga_random::ga_random_range(0, best_count), self.score_type_selection.population_sort_basis())
    }
}

pub struct GAUniformSelector<'a, T: 'a + GASolution>
{
    population: &'a mut GAPopulation<T>
}

impl<'a, T: GASolution> GAUniformSelector<'a, T>
{
    pub fn new(p: &'a mut GAPopulation<T>) -> GAUniformSelector<'a, T>
    {
        GAUniformSelector
        {
            population: p
        }
    }
}

impl<'a, T: GASolution> GASelector<'a, T> for GAUniformSelector<'a, T>
{
    fn assign(&mut self, population: &'a mut GAPopulation<T>)
    {
        self.population = population;
    }

    // Select any individual at random.
    fn select(&mut self) -> &T
    {
        // Need to sort first, because GAPopulation.individual() draws individuals
        // from the sorted lists.
        // TODO: GAPopulation should implement a method for selecting individuals
        // from the unsorted vector; GAUniformSelector would use it, because it
        // doesn't care about the order.
        self.population.sort();

        // Since selection is at random, it doesn't matter where the individual
        // is drawn from, the Raw/score-sorted or the Scaled/fitness-sorted list.
        self.population.individual(
            ga_random::ga_random_range(0, self.population.size()),
            GAPopulationSortBasis::Raw)
    }
}

//pub struct GARouletteWheelSelector<'a, T: 'a + GASolution>
//{
//    population: &'a mut GAPopulation<T>,
//
//    pop_sort_basis: GAPopulationSortBasis,
//
//    wheel_proportions: Vec<f32>,
//
//    wheel_is_dirty: bool
//}
//
//impl<'a, T: GASolution> GASelector<'a, T> for GARouletteWheelSelector<'a, T>
//{
//    fn assign(&mut self, population: &'a mut GAPopulation<T>)
//    {
//        self.population = population;
//
//        if self.population.size() != self.wheel_proportions.len()
//        {
//            self.wheel_proportions.resize(self.population.size(), 0.0);
//        }
//
//        self.wheel_is_dirty = true;
//    }
//
//    fn select(&mut self) -> &T
//    {
//        // Dummy.
//        self.population.individual(0, GAPopulationSortBasis::Raw)
//    }
//
//    fn update(&mut self)
//    {
//        // TODO: Replace with cached stats when implemented.
//        // TODO: Replace with best() and worst() once there is one for Raw and one for Scaled.
//        let max =  match self.pop_sort_basis
//                   {
//                        GAPopulationSortBasis::Raw    => self.population.individual(0, GAPopulationSortBasis::Raw).score(),
//                        GAPopulationSortBasis::Scaled => self.population.individual(0, GAPopulationSortBasis::Scaled).fitness()
//                   };
//
//        let min =  match self.pop_sort_basis
//                   {
//                        GAPopulationSortBasis::Raw    => self.population.individual(self.population.size()-1, GAPopulationSortBasis::Raw).score(),
//                        GAPopulationSortBasis::Scaled => self.population.individual(self.population.size()-1, GAPopulationSortBasis::Scaled).fitness()
//                   };
//    }
//}
<commit_msg>Add GARouletteWheelSelector.update()<commit_after>// TODO: COPYRIGHT, USE & AUTHORS
use super::ga_core::GASolution;
use super::ga_population::{GAPopulation, GAPopulationSortBasis, GAPopulationSortOrder};
use super::ga_random;

/// Selector Trait
///
/// Interface to Selection Schemes
pub trait GASelector<'a, T: GASolution>
{
    /// Assign the population on which to operate
    fn assign(&mut self, population: &'a mut GAPopulation<T>);
    /// Update internal state.
    /// Some selectors implement an empty update().
    fn update(&mut self) {}

    fn select(&mut self) -> &T;
}

pub trait GAScoreTypeBasedSelection<T: GASolution>
{
    fn score(&self, individual: &T) -> f32;

    fn population_sort_basis(&self) -> GAPopulationSortBasis;

    fn max_score(&self, population: &GAPopulation<T>) -> f32
    {
        // TODO: Knowing that best is at 0 is knowing too much.
        self.score(population.individual(0, self.population_sort_basis()))
    }

    fn min_score(&self, population: &GAPopulation<T>) -> f32
    {
        // TODO: Knowing that worst is at size()-1 is knowing too much.
        self.score(population.individual(population.size()-1, self.population_sort_basis()))
    }
}

pub struct GARawScoreBasedSelection;

impl<T: GASolution> GAScoreTypeBasedSelection<T> for GARawScoreBasedSelection
{
    fn score(&self, individual: &T) -> f32
    {
        individual.score()
    }

    fn population_sort_basis(&self) -> GAPopulationSortBasis
    {
        GAPopulationSortBasis::Raw
    }
}

pub struct GAScaledScoreBasedSelection;

impl<T: GASolution> GAScoreTypeBasedSelection<T> for GAScaledScoreBasedSelection
{
    fn score(&self, individual: &T) -> f32
    {
        individual.fitness()
    }

    fn population_sort_basis(&self) -> GAPopulationSortBasis
    {
        GAPopulationSortBasis::Scaled
    }
}

// GASolution-s live as long as the population. Lifetime 'a is bound to the
// population borrowed by the 'population' member, as well as to the enclosed
// GASolution-s, because they share the same memory.
pub struct GARankSelector<'a, T: 'a + GASolution>
{
    // Q: How to make this member common to all GASelectors?
    // Q: Will 'mut' make things more complex? When the rank selector is in
    //    scope and borrowing the population, no other objects will be able
    //    to borrow it, not even in non-mut mode according to the rules.
    // Selectors modify populations (they sort them, for instance), so the
    // reference must be 'mut'.
    population: &'a mut GAPopulation<T>,

    // TODO: Check correct lifetime.
    score_selection: &'a GAScoreTypeBasedSelection<T>
}

impl<'a, T: GASolution> GARankSelector<'a, T>
{
    pub fn new(p: &'a mut GAPopulation<T>, s: &'a GAScoreTypeBasedSelection<T>) -> GARankSelector<'a, T>
    {
        GARankSelector
        {
            population: p,
            score_selection: s
        }
    }
}

// TODO: DOC.
impl<'a, T: GASolution> GASelector<'a, T> for GARankSelector<'a, T>
{
    fn assign(&mut self, population: &'a mut GAPopulation<T>)
    {
        self.population = population;
    }

    fn select(&mut self) -> &T
    {
        // TODO: Confirm assumption that population has 1 individual at least.
        // Number of individuals that share best score.
        let mut best_count = 1;

        self.population.sort();

        // TODO: Use best() when implemented.
        // Q: Should individual() (ith_best()) return an optional or
        //    does it guarantee that it will always return something valid?
        //    What if the population is still empty?
        let best_score: f32 = self.score_selection.score(self.population.individual(0, self.score_selection.population_sort_basis()));

        // Skip 0th best.
        for i in 1..self.population.size()
        {
            if self.score_selection.score(self.population.individual(i, self.score_selection.population_sort_basis())) != best_score
            {
                break;
            }

            best_count = best_count + 1;
        }

        // Select any individual from those that share best score.
        self.population.individual(ga_random::ga_random_range(0, best_count), self.score_selection.population_sort_basis())
    }
}

pub struct GAUniformSelector<'a, T: 'a + GASolution>
{
    population: &'a mut GAPopulation<T>
}

impl<'a, T: GASolution> GAUniformSelector<'a, T>
{
    pub fn new(p: &'a mut GAPopulation<T>) -> GAUniformSelector<'a, T>
    {
        GAUniformSelector
        {
            population: p
        }
    }
}

impl<'a, T: GASolution> GASelector<'a, T> for GAUniformSelector<'a, T>
{
    fn assign(&mut self, population: &'a mut GAPopulation<T>)
    {
        self.population = population;
    }

    // Select any individual at random.
    fn select(&mut self) -> &T
    {
        // Need to sort first, because GAPopulation.individual() draws individuals
        // from the sorted lists.
        // TODO: GAPopulation should implement a method for selecting individuals
        // from the unsorted vector; GAUniformSelector would use it, because it
        // doesn't care about the order.
        self.population.sort();

        // Since selection is at random, it doesn't matter where the individual
        // is drawn from, the Raw/score-sorted or the Scaled/fitness-sorted list.
        self.population.individual(
            ga_random::ga_random_range(0, self.population.size()),
            GAPopulationSortBasis::Raw)
    }
}

pub struct GARouletteWheelSelector<'a, T: 'a + GASolution>
{
    population: &'a mut GAPopulation<T>,

    // TODO: Check correct lifetime.
    score_selection: &'a GAScoreTypeBasedSelection<T>,

    wheel_proportions: Vec<f32>,

    wheel_is_dirty: bool
}

impl<'a, T: GASolution> GARouletteWheelSelector<'a, T>
{
    // TODO: Check s's lifetime.
    pub fn new(p: &'a mut GAPopulation<T>,
               s: &'a GAScoreTypeBasedSelection<T>) -> GARouletteWheelSelector<'a, T>
    {
        // vec![] borrows references (invocation of size() is through *p, or so the
        // compiler says); since p has already been borrowed as a mutable reference
        // (no data races allowed), p.size() can't be passed to vec![].
        let wheel_size = p.size();

        GARouletteWheelSelector
        {
            population: p,
            score_selection: s,
            wheel_proportions: vec![0.0; wheel_size],
            wheel_is_dirty: false
        }
    }
}

impl<'a, T: GASolution> GASelector<'a, T> for GARouletteWheelSelector<'a, T>
{
    fn assign(&mut self, population: &'a mut GAPopulation<T>)
    {
        self.population = population;

        if self.population.size() != self.wheel_proportions.len()
        {
            self.wheel_proportions.resize(self.population.size(), 0.0);
        }

        self.wheel_is_dirty = true;
    }

    fn select(&mut self) -> &T
    {
        // Dummy.
        self.population.individual(0, GAPopulationSortBasis::Raw)
    }

    fn update(&mut self)
    {
        let wheel_slots = self.wheel_proportions.len();
        let max_score = self.score_selection.max_score(self.population);
        let min_score = self.score_selection.min_score(self.population);

        if max_score == min_score
        {
            // Upper bound is excluded.
            for i in 0..wheel_slots
            {
                self.wheel_proportions[i] = ((i+1) as f32)/(wheel_slots as f32);
            }
        }
        else if (max_score > 0.0 && min_score >= 0.0)
                 || (max_score <= 0.0 && min_score < 0.0)
        {
            // This is not a move, but a copy.
            let population_sort_basis = self.score_selection.population_sort_basis();

            self.population.sort();

            match self.population.order()
            {
                GAPopulationSortOrder::HighIsBest
                =>  {
                        self.wheel_proportions[0]
                          = self.score_selection.score(
                              self.population.individual(0, population_sort_basis));

                        for i in 1..wheel_slots
                        {
                            self.wheel_proportions[i]
                              = self.score_selection.score(
                                  self.population.individual(i, population_sort_basis))
                                + self.wheel_proportions[i-1];
                        }

                        for i in 1..wheel_slots
                        {
                            self.wheel_proportions[i]
                              /= self.wheel_proportions[wheel_slots-1];
                        }
                    },
                GAPopulationSortOrder::LowIsBest
                =>  {
                        self.wheel_proportions[0]
                          = -self.score_selection.score(
                               self.population.individual(0, population_sort_basis))
                            + max_score + min_score;

                        for i in 1..wheel_slots
                        {
                            self.wheel_proportions[i]
                              = -self.score_selection.score(
                                   self.population.individual(i, population_sort_basis))
                                + max_score + min_score
                                + self.wheel_proportions[wheel_slots-1];
                        }

                        for i in 1..wheel_slots
                        {
                            self.wheel_proportions[i]
                              /= self.wheel_proportions[wheel_slots-1];
                        }
                    }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Items related to the edges of a geometry graph.
use daggy;
use math::{BaseFloat, Euler, Rad, Vector3};

/// Unique index for an **Edge** within a **Graph**.
pub type Index = daggy::EdgeIndex<usize>;

/// An iterator yielding multiple `Index`es.
pub type Indices = daggy::EdgeIndices<usize>;

/// Describes an edge within the geometry graph.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Edge<S> {
    /// The unique kind of edge.
    ///
    /// Represents the combination of `Axis` and `Relative` association described by the edge.
    pub kind: Kind,
    /// A weight whose value's meaning depends on the edge's `Relative` association.
    ///
    /// For `Position` kind edges this represents a relative scalar value.
    /// For `Orientation` kind edges this represents a relative angle in radians.
    /// For `Scale` kind edges this represents the relative scale.
    pub weight: S,
}

/// The unique `Edge` kind - a combo of a `Relative` association and an `Axis`.
///
/// Every incoming (parent) `Edge` for each `Node` in the graph *must* be a unique kind. E.g.
/// it does not make sense for a `Node` to be positioned relatively along the *x* axis to two
/// different parent `Node`s.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Kind {
    /// The axis along which this edge describes some relationship.
    pub axis: Axis,
    /// The relative association described by the edge.
    pub relative: Relative,
}

/// Describes one of the three axes in three-dimensional space.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum Axis {
    X,
    Y,
    Z,
}

/// The various possible relative relationships that can be created between nodes.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Relative {
    /// A relative position as a scalar value.
    Position,
    /// A relative orientation in radians.
    Orientation,
    /// A relative scale.
    Scale,
}

impl Kind {
    /// Simple constructor for an edge `Kind`.
    pub fn new(axis: Axis, relative: Relative) -> Self {
        Kind { axis, relative }
    }

    /// Simple constructor for and Edge describing a relative association over the **X** axis.
    pub fn x(relative: Relative) -> Self {
        Kind::new(Axis::X, relative)
    }

    /// Simple constructor for and Edge describing a relative association over the **Y** axis.
    pub fn y(relative: Relative) -> Self {
        Kind::new(Axis::Y, relative)
    }

    /// Simple constructor for and Edge describing a relative association over the **Z** axis.
    pub fn z(relative: Relative) -> Self {
        Kind::new(Axis::Z, relative)
    }

    /// Simple constructor for and Edge describing a relative position over the **X** axis.
    pub fn x_position() -> Self {
        Kind::x(Relative::Position)
    }

    /// Simple constructor for and Edge describing a relative orientation over the **X** axis.
    pub fn x_orientation() -> Self {
        Kind::x(Relative::Orientation)
    }

    /// Simple constructor for and Edge describing a relative scale over the **X** axis.
    pub fn x_scale() -> Self {
        Kind::x(Relative::Scale)
    }

    /// Simple constructor for and Edge describing a relative position over the **Y** axis.
    pub fn y_position() -> Self {
        Kind::y(Relative::Position)
    }

    /// Simple constructor for and Edge describing a relative orientation over the **Y** axis.
    pub fn y_orientation() -> Self {
        Kind::y(Relative::Orientation)
    }

    /// Simple constructor for and Edge describing a relative scale over the **Y** axis.
    pub fn y_scale() -> Self {
        Kind::y(Relative::Scale)
    }

    /// Simple constructor for and Edge describing a relative position over the **Z** axis.
    pub fn z_position() -> Self {
        Kind::z(Relative::Position)
    }

    /// Simple constructor for and Edge describing a relative orientation over the **Z** axis.
    pub fn z_orientation() -> Self {
        Kind::z(Relative::Orientation)
    }

    /// Simple constructor for and Edge describing a relative scale over the **Z** axis.
    pub fn z_scale() -> Self {
        Kind::z(Relative::Scale)
    }
}

impl<S> Edge<S> {
    /// Simple constructor for an `Edge`.
    pub fn new(kind: Kind, weight: S) -> Self {
        Edge { kind, weight }
    }

    /// Simple constructor for an `Edge` describing a relative association over the **X** axis.
    pub fn x(relative: Relative, weight: S) -> Self {
        Edge::new(Kind::x(relative), weight)
    }

    /// Simple constructor for an `Edge` describing a relative association over the **Y** axis.
    pub fn y(relative: Relative, weight: S) -> Self {
        Edge::new(Kind::y(relative), weight)
    }

    /// Simple constructor for an `Edge` describing a relative association over the **Z** axis.
    pub fn z(relative: Relative, weight: S) -> Self {
        Edge::new(Kind::z(relative), weight)
    }

    /// Simple constructor for an `Edge` describing a relative position over the **X** axis.
    pub fn x_position(weight: S) -> Self {
        Edge::new(Kind::x_position(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative orientation over the **X** axis.
    pub fn x_orientation(weight: S) -> Self {
        Edge::new(Kind::x_orientation(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative scale over the **X** axis.
    pub fn x_scale(weight: S) -> Self {
        Edge::new(Kind::x_scale(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative position over the **Y** axis.
    pub fn y_position(weight: S) -> Self {
        Edge::new(Kind::y_position(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative orientation over the **Y** axis.
    pub fn y_orientation(weight: S) -> Self {
        Edge::new(Kind::y_orientation(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative scale over the **Y** axis.
    pub fn y_scale(weight: S) -> Self {
        Edge::new(Kind::y_scale(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative position over the **Z** axis.
    pub fn z_position(weight: S) -> Self {
        Edge::new(Kind::z_position(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative orientation over the **Z** axis.
    pub fn z_orientation(weight: S) -> Self {
        Edge::new(Kind::z_orientation(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative scale over the **Z** axis.
    pub fn z_scale(weight: S) -> Self {
        Edge::new(Kind::z_scale(), weight)
    }
}

/// The three edges describing the given position displacement.
pub fn displace<S>(v: Vector3<S>) -> [Edge<S>; 3] {
    [Edge::x_position(v.x), Edge::y_position(v.y), Edge::z_position(v.z)]
}

/// The three edges describing the given orientation rotation.
pub fn rotate<S: BaseFloat>(e: Euler<Rad<S>>) -> [Edge<S>; 3] {
    [Edge::x_orientation(e.x.0), Edge::y_orientation(e.x.0), Edge::z_orientation(e.z.0)]
}

/// An edge for scaling each axis using the given single scalar scale value.
pub fn scale<S: Copy>(scale: S) -> [Edge<S>; 3] {
    [Edge::x_scale(scale), Edge::y_scale(scale), Edge::z_scale(scale)]
}
<commit_msg>Add position, orientation and scale constructors to geom::graph::Edge<commit_after>//! Items related to the edges of a geometry graph.
use daggy;
use math::{BaseFloat, Euler, Rad, Vector3};

/// Unique index for an **Edge** within a **Graph**.
pub type Index = daggy::EdgeIndex<usize>;

/// An iterator yielding multiple `Index`es.
pub type Indices = daggy::EdgeIndices<usize>;

/// Describes an edge within the geometry graph.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Edge<S> {
    /// The unique kind of edge.
    ///
    /// Represents the combination of `Axis` and `Relative` association described by the edge.
    pub kind: Kind,
    /// A weight whose value's meaning depends on the edge's `Relative` association.
    ///
    /// For `Position` kind edges this represents a relative scalar value.
    /// For `Orientation` kind edges this represents a relative angle in radians.
    /// For `Scale` kind edges this represents the relative scale.
    pub weight: S,
}

/// The unique `Edge` kind - a combo of a `Relative` association and an `Axis`.
///
/// Every incoming (parent) `Edge` for each `Node` in the graph *must* be a unique kind. E.g.
/// it does not make sense for a `Node` to be positioned relatively along the *x* axis to two
/// different parent `Node`s.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Kind {
    /// The axis along which this edge describes some relationship.
    pub axis: Axis,
    /// The relative association described by the edge.
    pub relative: Relative,
}

/// Describes one of the three axes in three-dimensional space.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum Axis {
    X,
    Y,
    Z,
}

/// The various possible relative relationships that can be created between nodes.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Relative {
    /// A relative position as a scalar value.
    Position,
    /// A relative orientation in radians.
    Orientation,
    /// A relative scale.
    Scale,
}

impl Kind {
    /// Simple constructor for an edge `Kind`.
    pub fn new(axis: Axis, relative: Relative) -> Self {
        Kind { axis, relative }
    }

    /// Simple constructor for and Edge describing a relative association over the **X** axis.
    pub fn x(relative: Relative) -> Self {
        Kind::new(Axis::X, relative)
    }

    /// Simple constructor for and Edge describing a relative association over the **Y** axis.
    pub fn y(relative: Relative) -> Self {
        Kind::new(Axis::Y, relative)
    }

    /// Simple constructor for and Edge describing a relative association over the **Z** axis.
    pub fn z(relative: Relative) -> Self {
        Kind::new(Axis::Z, relative)
    }

    /// Simple constructor for an Edge describing a relative position along the given axis.
    pub fn position(axis: Axis) -> Self {
        let relative = Relative::Position;
        Kind { axis, relative }
    }

    /// Simple constructor for an Edge describing a relative orientation along the given axis.
    pub fn orientation(axis: Axis) -> Self {
        let relative = Relative::Orientation;
        Kind { axis, relative }
    }

    /// Simple constructor for an Edge describing a relative scale along the given axis.
    pub fn scale(axis: Axis) -> Self {
        let relative = Relative::Scale;
        Kind { axis, relative }
    }

    /// Simple constructor for and Edge describing a relative position over the **X** axis.
    pub fn x_position() -> Self {
        Kind::x(Relative::Position)
    }

    /// Simple constructor for and Edge describing a relative orientation over the **X** axis.
    pub fn x_orientation() -> Self {
        Kind::x(Relative::Orientation)
    }

    /// Simple constructor for and Edge describing a relative scale over the **X** axis.
    pub fn x_scale() -> Self {
        Kind::x(Relative::Scale)
    }

    /// Simple constructor for and Edge describing a relative position over the **Y** axis.
    pub fn y_position() -> Self {
        Kind::y(Relative::Position)
    }

    /// Simple constructor for and Edge describing a relative orientation over the **Y** axis.
    pub fn y_orientation() -> Self {
        Kind::y(Relative::Orientation)
    }

    /// Simple constructor for and Edge describing a relative scale over the **Y** axis.
    pub fn y_scale() -> Self {
        Kind::y(Relative::Scale)
    }

    /// Simple constructor for and Edge describing a relative position over the **Z** axis.
    pub fn z_position() -> Self {
        Kind::z(Relative::Position)
    }

    /// Simple constructor for and Edge describing a relative orientation over the **Z** axis.
    pub fn z_orientation() -> Self {
        Kind::z(Relative::Orientation)
    }

    /// Simple constructor for and Edge describing a relative scale over the **Z** axis.
    pub fn z_scale() -> Self {
        Kind::z(Relative::Scale)
    }
}

impl<S> Edge<S> {
    /// Simple constructor for an `Edge`.
    pub fn new(kind: Kind, weight: S) -> Self {
        Edge { kind, weight }
    }

    /// Simple constructor for an `Edge` describing a relative association over the **X** axis.
    pub fn x(relative: Relative, weight: S) -> Self {
        Edge::new(Kind::x(relative), weight)
    }

    /// Simple constructor for an `Edge` describing a relative association over the **Y** axis.
    pub fn y(relative: Relative, weight: S) -> Self {
        Edge::new(Kind::y(relative), weight)
    }

    /// Simple constructor for an `Edge` describing a relative association over the **Z** axis.
    pub fn z(relative: Relative, weight: S) -> Self {
        Edge::new(Kind::z(relative), weight)
    }

    /// Simple constructor for an `Edge` describing a relative position over the given axis.
    pub fn position(axis: Axis, weight: S) -> Self {
        Edge::new(Kind::position(axis), weight)
    }

    /// Simple constructor for an `Edge` describing a relative orientation over the given axis.
    pub fn orientation(axis: Axis, weight: S) -> Self {
        Edge::new(Kind::orientation(axis), weight)
    }

    /// Simple constructor for an `Edge` describing a relative scale over the given axis.
    pub fn scale(axis: Axis, weight: S) -> Self {
        Edge::new(Kind::scale(axis), weight)
    }

    /// Simple constructor for an `Edge` describing a relative position over the **X** axis.
    pub fn x_position(weight: S) -> Self {
        Edge::new(Kind::x_position(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative orientation over the **X** axis.
    pub fn x_orientation(weight: S) -> Self {
        Edge::new(Kind::x_orientation(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative scale over the **X** axis.
    pub fn x_scale(weight: S) -> Self {
        Edge::new(Kind::x_scale(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative position over the **Y** axis.
    pub fn y_position(weight: S) -> Self {
        Edge::new(Kind::y_position(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative orientation over the **Y** axis.
    pub fn y_orientation(weight: S) -> Self {
        Edge::new(Kind::y_orientation(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative scale over the **Y** axis.
    pub fn y_scale(weight: S) -> Self {
        Edge::new(Kind::y_scale(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative position over the **Z** axis.
    pub fn z_position(weight: S) -> Self {
        Edge::new(Kind::z_position(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative orientation over the **Z** axis.
    pub fn z_orientation(weight: S) -> Self {
        Edge::new(Kind::z_orientation(), weight)
    }

    /// Simple constructor for an `Edge` describing a relative scale over the **Z** axis.
    pub fn z_scale(weight: S) -> Self {
        Edge::new(Kind::z_scale(), weight)
    }
}

/// The three edges describing the given position displacement.
pub fn displace<S>(v: Vector3<S>) -> [Edge<S>; 3] {
    [Edge::x_position(v.x), Edge::y_position(v.y), Edge::z_position(v.z)]
}

/// The three edges describing the given orientation rotation.
pub fn rotate<S: BaseFloat>(e: Euler<Rad<S>>) -> [Edge<S>; 3] {
    [Edge::x_orientation(e.x.0), Edge::y_orientation(e.x.0), Edge::z_orientation(e.z.0)]
}

/// An edge for scaling each axis using the given single scalar scale value.
pub fn scale<S: Copy>(scale: S) -> [Edge<S>; 3] {
    [Edge::x_scale(scale), Edge::y_scale(scale), Edge::z_scale(scale)]
}
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp::min;
use std::result;

use sys_util::{GuestAddress, GuestMemory};

const VIRTQ_DESC_F_NEXT: u16 = 0x1;
const VIRTQ_DESC_F_WRITE: u16 = 0x2;
#[allow(dead_code)]
const VIRTQ_DESC_F_INDIRECT: u16 = 0x4;

#[derive(Clone, Debug)]
pub enum Error {
    RequestOutOfBounds,
    SectorOutOfBounds,
}
pub type Result<T> = result::Result<T, Error>;

/// A virtio descriptor chain.
pub struct DescriptorChain<'a> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    queue_size: u16,
    ttl: u16, // used to prevent infinite chain cycles

    /// Index into the descriptor table
    pub index: u16,

    /// Guest physical address of device specific data
    pub addr: GuestAddress,

    /// Length of device specific data
    pub len: u32,

    /// Includes next, write, and indirect bits
    pub flags: u16,

    /// Index into the descriptor table of the next descriptor if flags has
    /// the next bit set
    pub next: u16,
}

impl<'a> DescriptorChain<'a> {
    fn checked_new(mem: &GuestMemory,
                   desc_table: GuestAddress,
                   queue_size: u16,
                   index: u16)
                   -> Option<DescriptorChain> {
        if index >= queue_size {
            return None;
        }

        let desc_head = match mem.checked_offset(desc_table, (index as usize) * 16) {
            Some(a) => a,
            None => return None,
        };
        // These reads can't fail unless Guest memory is hopelessly broken.
        let addr = GuestAddress(mem.read_obj_from_addr::<u64>(desc_head).unwrap() as usize);
        if mem.checked_offset(desc_head, 16).is_none() {
            return None;
        }
        let len: u32 = mem.read_obj_from_addr(desc_head.unchecked_add(8))
            .unwrap();
        let flags: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(12))
            .unwrap();
        let next: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(14))
            .unwrap();
        let chain = DescriptorChain {
            mem: mem,
            desc_table: desc_table,
            queue_size: queue_size,
            ttl: queue_size,
            index: index,
            addr: addr,
            len: len,
            flags: flags,
            next: next,
        };

        if chain.is_valid() { Some(chain) } else { None }
    }

    fn is_valid(&self) -> bool {
        if self.mem
               .checked_offset(self.addr, self.len as usize)
               .is_none() {
            false
        } else if self.has_next() && self.next >= self.queue_size {
            false
        } else {
            true
        }
    }

    /// Gets if this descriptor chain has another descriptor chain linked after it.
    pub fn has_next(&self) -> bool {
        self.flags & VIRTQ_DESC_F_NEXT != 0 && self.ttl > 1
    }

    /// If the driver designated this as a write only descriptor.
    ///
    /// If this is false, this descriptor is read only.
    pub fn is_write_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE != 0
    }

    /// Gets the next descriptor in this descriptor chain, if there is one.
    ///
    /// Note that this is distinct from the next descriptor chain returned by `AvailIter`, which is
    /// the head of the next _available_ descriptor chain.
    pub fn next_descriptor(&self) -> Option<DescriptorChain<'a>> {
        if self.has_next() {
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, self.next)
                .map(|mut c| {
                         c.ttl = self.ttl - 1;
                         c
                     })
        } else {
            None
        }
    }
}

/// Consuming iterator over all available descriptor chain heads in the queue.
pub struct AvailIter<'a, 'b> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    avail_ring: GuestAddress,
    next_index: usize,
    last_index: usize,
    queue_size: usize,
    next_avail: &'b mut u16,
}

impl<'a, 'b> Iterator for AvailIter<'a, 'b> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.next_index == self.last_index {
            return None;
        }

        let avail_addr = match self.mem
                  .checked_offset(self.avail_ring, 4 + self.next_index * 2) {
            Some(a) => a,
            None => return None,
        };
        // This index is checked below in checked_new
        let desc_index: u16 = self.mem.read_obj_from_addr(avail_addr).unwrap();

        self.next_index += 1;
        self.next_index %= self.queue_size;

        let ret = DescriptorChain::checked_new(self.mem,
                                               self.desc_table,
                                               self.queue_size as u16,
                                               desc_index);
        if ret.is_some() {
            *self.next_avail += 1;
            *self.next_avail %= self.queue_size as u16;
        }
        ret
    }
}

#[derive(Clone)]
/// A virtio queue's parameters.
pub struct Queue {
    /// The maximal size in elements offered by the device
    pub max_size: u16,

    /// The queue size in elements the driver selected
    pub size: u16,

    /// Inidcates if the queue is finished with configuration
    pub ready: bool,

    /// Guest physical address of the descriptor table
    pub desc_table: GuestAddress,

    /// Guest physical address of the available ring
    pub avail_ring: GuestAddress,

    /// Guest physical address of the used ring
    pub used_ring: GuestAddress,

    next_avail: u16,
    next_used: u16,
}

impl Queue {
    /// Constructs an empty virtio queue with the given `max_size`.
    pub fn new(max_size: u16) -> Queue {
        Queue {
            max_size: max_size,
            size: 0,
            ready: false,
            desc_table: GuestAddress(0),
            avail_ring: GuestAddress(0),
            used_ring: GuestAddress(0),
            next_avail: 0,
            next_used: 0,
        }
    }

    fn actual_size(&self) -> u16 {
        min(self.size, self.max_size)
    }

    fn is_valid(&self, mem: &GuestMemory) -> bool {
        let queue_size = self.actual_size() as usize;
        let desc_table = self.desc_table;
        let desc_table_size = 16 * queue_size;
        let avail_ring = self.avail_ring;
        let avail_ring_size = 6 + 2 * queue_size;
        let used_ring = self.used_ring;
        let used_ring_size = 6 + 8 * queue_size;
        if !self.ready {
            println!("error: attempt to use virtio queue that is not marked ready");
            false
        } else if self.size > self.max_size || self.size == 0 ||
                  (self.size & (self.size - 1)) != 0 {
            println!("error: virtio queue with invalid size: {}", self.size);
            false
        } else if desc_table
                      .checked_add(desc_table_size)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            println!("error: virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}",
                     desc_table.offset(),
                     desc_table_size);
            false
        } else if avail_ring
                      .checked_add(avail_ring_size)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            println!("error: virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                     avail_ring.offset(),
                     avail_ring_size);
            false
        } else if used_ring
                      .checked_add(used_ring_size)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            println!("error: virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                     used_ring.offset(),
                     used_ring_size);
            false
        } else {
            true
        }

    }

    /// A consuming iterator over all available descriptor chain heads offered by the driver.
    pub fn iter<'a, 'b>(&'b mut self, mem: &'a GuestMemory) -> AvailIter<'a, 'b> {
        if !self.is_valid(mem) {
            return AvailIter {
                       mem: mem,
                       desc_table: GuestAddress(0),
                       avail_ring: GuestAddress(0),
                       next_index: 0,
                       last_index: 0,
                       queue_size: 0,
                       next_avail: &mut self.next_avail,
                   };
        }
        let queue_size = self.actual_size();
        let avail_ring = self.avail_ring;

        let index_addr = mem.checked_offset(avail_ring, 2).unwrap();
        // Note that last_index has no invalid values
        let last_index: u16 = mem.read_obj_from_addr::<u16>(index_addr).unwrap() % queue_size;
        AvailIter {
            mem: mem,
            desc_table: self.desc_table,
            avail_ring: avail_ring,
            next_index: self.next_avail as usize,
            last_index: last_index as usize,
            queue_size: queue_size as usize,
            next_avail: &mut self.next_avail,
        }
    }

    /// Puts an available descriptor head into the used ring for use by the guest.
    pub fn add_used(&mut self, mem: &GuestMemory, desc_index: u16, len: u32) {
        if desc_index >= self.actual_size() {
            println!("error: attempted to add out of bounds descriptor to used ring: {}",
                     desc_index);
            return;
        }

        let used_ring = self.used_ring;
        let next_used = (self.next_used % self.actual_size()) as usize;
        let used_elem = used_ring.unchecked_add(4 + next_used * 8);

        // These writes can't fail as we are guaranteed to be within the descriptor ring.
        mem.write_obj_at_addr(desc_index as u32, used_elem)
            .unwrap();
        mem.write_obj_at_addr(len as u32, used_elem.unchecked_add(4))
            .unwrap();

        self.next_used = self.next_used.wrapping_add(1);
        mem.write_obj_at_addr(self.next_used as u16, used_ring.unchecked_add(2))
            .unwrap();
    }
}
<commit_msg>crosvm: remove unusued error type from hw::virtio::queue<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp::min;
use std::result;

use sys_util::{GuestAddress, GuestMemory};

const VIRTQ_DESC_F_NEXT: u16 = 0x1;
const VIRTQ_DESC_F_WRITE: u16 = 0x2;
#[allow(dead_code)]
const VIRTQ_DESC_F_INDIRECT: u16 = 0x4;

/// A virtio descriptor chain.
pub struct DescriptorChain<'a> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    queue_size: u16,
    ttl: u16, // used to prevent infinite chain cycles

    /// Index into the descriptor table
    pub index: u16,

    /// Guest physical address of device specific data
    pub addr: GuestAddress,

    /// Length of device specific data
    pub len: u32,

    /// Includes next, write, and indirect bits
    pub flags: u16,

    /// Index into the descriptor table of the next descriptor if flags has
    /// the next bit set
    pub next: u16,
}

impl<'a> DescriptorChain<'a> {
    fn checked_new(mem: &GuestMemory,
                   desc_table: GuestAddress,
                   queue_size: u16,
                   index: u16)
                   -> Option<DescriptorChain> {
        if index >= queue_size {
            return None;
        }

        let desc_head = match mem.checked_offset(desc_table, (index as usize) * 16) {
            Some(a) => a,
            None => return None,
        };
        // These reads can't fail unless Guest memory is hopelessly broken.
        let addr = GuestAddress(mem.read_obj_from_addr::<u64>(desc_head).unwrap() as usize);
        if mem.checked_offset(desc_head, 16).is_none() {
            return None;
        }
        let len: u32 = mem.read_obj_from_addr(desc_head.unchecked_add(8))
            .unwrap();
        let flags: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(12))
            .unwrap();
        let next: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(14))
            .unwrap();
        let chain = DescriptorChain {
            mem: mem,
            desc_table: desc_table,
            queue_size: queue_size,
            ttl: queue_size,
            index: index,
            addr: addr,
            len: len,
            flags: flags,
            next: next,
        };

        if chain.is_valid() { Some(chain) } else { None }
    }

    fn is_valid(&self) -> bool {
        if self.mem
               .checked_offset(self.addr, self.len as usize)
               .is_none() {
            false
        } else if self.has_next() && self.next >= self.queue_size {
            false
        } else {
            true
        }
    }

    /// Gets if this descriptor chain has another descriptor chain linked after it.
    pub fn has_next(&self) -> bool {
        self.flags & VIRTQ_DESC_F_NEXT != 0 && self.ttl > 1
    }

    /// If the driver designated this as a write only descriptor.
    ///
    /// If this is false, this descriptor is read only.
    pub fn is_write_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE != 0
    }

    /// Gets the next descriptor in this descriptor chain, if there is one.
    ///
    /// Note that this is distinct from the next descriptor chain returned by `AvailIter`, which is
    /// the head of the next _available_ descriptor chain.
    pub fn next_descriptor(&self) -> Option<DescriptorChain<'a>> {
        if self.has_next() {
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, self.next)
                .map(|mut c| {
                         c.ttl = self.ttl - 1;
                         c
                     })
        } else {
            None
        }
    }
}

/// Consuming iterator over all available descriptor chain heads in the queue.
pub struct AvailIter<'a, 'b> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    avail_ring: GuestAddress,
    next_index: usize,
    last_index: usize,
    queue_size: usize,
    next_avail: &'b mut u16,
}

impl<'a, 'b> Iterator for AvailIter<'a, 'b> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.next_index == self.last_index {
            return None;
        }

        let avail_addr = match self.mem
                  .checked_offset(self.avail_ring, 4 + self.next_index * 2) {
            Some(a) => a,
            None => return None,
        };
        // This index is checked below in checked_new
        let desc_index: u16 = self.mem.read_obj_from_addr(avail_addr).unwrap();

        self.next_index += 1;
        self.next_index %= self.queue_size;

        let ret = DescriptorChain::checked_new(self.mem,
                                               self.desc_table,
                                               self.queue_size as u16,
                                               desc_index);
        if ret.is_some() {
            *self.next_avail += 1;
            *self.next_avail %= self.queue_size as u16;
        }
        ret
    }
}

#[derive(Clone)]
/// A virtio queue's parameters.
pub struct Queue {
    /// The maximal size in elements offered by the device
    pub max_size: u16,

    /// The queue size in elements the driver selected
    pub size: u16,

    /// Inidcates if the queue is finished with configuration
    pub ready: bool,

    /// Guest physical address of the descriptor table
    pub desc_table: GuestAddress,

    /// Guest physical address of the available ring
    pub avail_ring: GuestAddress,

    /// Guest physical address of the used ring
    pub used_ring: GuestAddress,

    next_avail: u16,
    next_used: u16,
}

impl Queue {
    /// Constructs an empty virtio queue with the given `max_size`.
    pub fn new(max_size: u16) -> Queue {
        Queue {
            max_size: max_size,
            size: 0,
            ready: false,
            desc_table: GuestAddress(0),
            avail_ring: GuestAddress(0),
            used_ring: GuestAddress(0),
            next_avail: 0,
            next_used: 0,
        }
    }

    fn actual_size(&self) -> u16 {
        min(self.size, self.max_size)
    }

    fn is_valid(&self, mem: &GuestMemory) -> bool {
        let queue_size = self.actual_size() as usize;
        let desc_table = self.desc_table;
        let desc_table_size = 16 * queue_size;
        let avail_ring = self.avail_ring;
        let avail_ring_size = 6 + 2 * queue_size;
        let used_ring = self.used_ring;
        let used_ring_size = 6 + 8 * queue_size;
        if !self.ready {
            println!("error: attempt to use virtio queue that is not marked ready");
            false
        } else if self.size > self.max_size || self.size == 0 ||
                  (self.size & (self.size - 1)) != 0 {
            println!("error: virtio queue with invalid size: {}", self.size);
            false
        } else if desc_table
                      .checked_add(desc_table_size)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            println!("error: virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}",
                     desc_table.offset(),
                     desc_table_size);
            false
        } else if avail_ring
                      .checked_add(avail_ring_size)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            println!("error: virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                     avail_ring.offset(),
                     avail_ring_size);
            false
        } else if used_ring
                      .checked_add(used_ring_size)
                      .map_or(true, |v| !mem.address_in_range(v)) {
            println!("error: virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                     used_ring.offset(),
                     used_ring_size);
            false
        } else {
            true
        }

    }

    /// A consuming iterator over all available descriptor chain heads offered by the driver.
    pub fn iter<'a, 'b>(&'b mut self, mem: &'a GuestMemory) -> AvailIter<'a, 'b> {
        if !self.is_valid(mem) {
            return AvailIter {
                       mem: mem,
                       desc_table: GuestAddress(0),
                       avail_ring: GuestAddress(0),
                       next_index: 0,
                       last_index: 0,
                       queue_size: 0,
                       next_avail: &mut self.next_avail,
                   };
        }
        let queue_size = self.actual_size();
        let avail_ring = self.avail_ring;

        let index_addr = mem.checked_offset(avail_ring, 2).unwrap();
        // Note that last_index has no invalid values
        let last_index: u16 = mem.read_obj_from_addr::<u16>(index_addr).unwrap() % queue_size;
        AvailIter {
            mem: mem,
            desc_table: self.desc_table,
            avail_ring: avail_ring,
            next_index: self.next_avail as usize,
            last_index: last_index as usize,
            queue_size: queue_size as usize,
            next_avail: &mut self.next_avail,
        }
    }

    /// Puts an available descriptor head into the used ring for use by the guest.
    pub fn add_used(&mut self, mem: &GuestMemory, desc_index: u16, len: u32) {
        if desc_index >= self.actual_size() {
            println!("error: attempted to add out of bounds descriptor to used ring: {}",
                     desc_index);
            return;
        }

        let used_ring = self.used_ring;
        let next_used = (self.next_used % self.actual_size()) as usize;
        let used_elem = used_ring.unchecked_add(4 + next_used * 8);

        // These writes can't fail as we are guaranteed to be within the descriptor ring.
        mem.write_obj_at_addr(desc_index as u32, used_elem)
            .unwrap();
        mem.write_obj_at_addr(len as u32, used_elem.unchecked_add(4))
            .unwrap();

        self.next_used = self.next_used.wrapping_add(1);
        mem.write_obj_at_addr(self.next_used as u16, used_ring.unchecked_add(2))
            .unwrap();
    }
}
<|endoftext|>


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

//! Failure support for libcore
//!
//! The core library cannot define failure, but it does *declare* failure. This
//! means that the functions inside of libcore are allowed to fail, but to be
//! useful an upstream crate must define failure for libcore to use. The current
//! interface for failure is:
//!
//! ```ignore
//! fn begin_unwind(fmt: &fmt::Arguments, file: &str, line: uint) -> !;
//! ```
//!
//! This definition allows for failing with any general message, but it does not
//! allow for failing with a `~Any` value. The reason for this is that libcore
//! is not allowed to allocate.
//!
//! This module contains a few other failure functions, but these are just the
//! necessary lang items for the compiler. All failure is funneled through this
//! one function. Currently, the actual symbol is declared in the standard
//! library, but the location of this may change over time.

#![allow(dead_code, missing_doc)]

use fmt;
use intrinsics;

#[cfg(stage0)]
#[cold] #[inline(never)] // this is the slow path, always
#[lang="fail_"]
fn fail_(expr: &'static str, file: &'static str, line: uint) -> ! {
    format_args!(|args| -> () {
        begin_unwind(args, &(file, line));
    }, "{}", expr);

    unsafe { intrinsics::abort() }
}

#[cfg(stage0)]
#[cold]
#[lang="fail_bounds_check"]
fn fail_bounds_check(file: &'static str, line: uint,
                     index: uint, len: uint) -> ! {
    format_args!(|args| -> () {
        begin_unwind(args, &(file, line));
    }, "index out of bounds: the len is {} but the index is {}", len, index);
    unsafe { intrinsics::abort() }
}

#[cfg(not(stage0))]
#[cold] #[inline(never)] // this is the slow path, always
#[lang="fail_"]
fn fail_(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
    let (expr, file, line) = *expr_file_line;
    let ref file_line = (file, line);
    format_args!(|args| -> () {
        begin_unwind(args, file_line);
    }, "{}", expr);

    unsafe { intrinsics::abort() }
}

#[cfg(not(stage0))]
#[cold]
#[lang="fail_bounds_check"]
fn fail_bounds_check(file_line: &(&'static str, uint),
                     index: uint, len: uint) -> ! {
    format_args!(|args| -> () {
        begin_unwind(args, file_line);
    }, "index out of bounds: the len is {} but the index is {}", len, index);
    unsafe { intrinsics::abort() }
}

#[cold]
pub fn begin_unwind(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
    #[allow(ctypes)]
    extern {
        #[lang = "begin_unwind"]
        fn begin_unwind(fmt: &fmt::Arguments, file: &'static str,
                        line: uint) -> !;
    }
    let (file, line) = *file_line;
    unsafe { begin_unwind(fmt, file, line) }
}

<commit_msg>core: Add #[inline(never)] to failure functions<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Failure support for libcore
//!
//! The core library cannot define failure, but it does *declare* failure. This
//! means that the functions inside of libcore are allowed to fail, but to be
//! useful an upstream crate must define failure for libcore to use. The current
//! interface for failure is:
//!
//! ```ignore
//! fn begin_unwind(fmt: &fmt::Arguments, file: &str, line: uint) -> !;
//! ```
//!
//! This definition allows for failing with any general message, but it does not
//! allow for failing with a `~Any` value. The reason for this is that libcore
//! is not allowed to allocate.
//!
//! This module contains a few other failure functions, but these are just the
//! necessary lang items for the compiler. All failure is funneled through this
//! one function. Currently, the actual symbol is declared in the standard
//! library, but the location of this may change over time.

#![allow(dead_code, missing_doc)]

use fmt;
use intrinsics;

#[cfg(stage0)]
#[cold] #[inline(never)] // this is the slow path, always
#[lang="fail_"]
fn fail_(expr: &'static str, file: &'static str, line: uint) -> ! {
    format_args!(|args| -> () {
        begin_unwind(args, &(file, line));
    }, "{}", expr);

    unsafe { intrinsics::abort() }
}

#[cfg(stage0)]
#[cold]
#[lang="fail_bounds_check"]
fn fail_bounds_check(file: &'static str, line: uint,
                     index: uint, len: uint) -> ! {
    format_args!(|args| -> () {
        begin_unwind(args, &(file, line));
    }, "index out of bounds: the len is {} but the index is {}", len, index);
    unsafe { intrinsics::abort() }
}

#[cfg(not(stage0))]
#[cold] #[inline(never)] // this is the slow path, always
#[lang="fail_"]
fn fail_(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
    let (expr, file, line) = *expr_file_line;
    let ref file_line = (file, line);
    format_args!(|args| -> () {
        begin_unwind(args, file_line);
    }, "{}", expr);

    unsafe { intrinsics::abort() }
}

#[cfg(not(stage0))]
#[cold] #[inline(never)]
#[lang="fail_bounds_check"]
fn fail_bounds_check(file_line: &(&'static str, uint),
                     index: uint, len: uint) -> ! {
    format_args!(|args| -> () {
        begin_unwind(args, file_line);
    }, "index out of bounds: the len is {} but the index is {}", len, index);
    unsafe { intrinsics::abort() }
}

#[cold] #[inline(never)]
pub fn begin_unwind(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
    #[allow(ctypes)]
    extern {
        #[lang = "begin_unwind"]
        fn begin_unwind(fmt: &fmt::Arguments, file: &'static str,
                        line: uint) -> !;
    }
    let (file, line) = *file_line;
    unsafe { begin_unwind(fmt, file, line) }
}

<|endoftext|>