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

//! Complex numbers.

use std::fmt;
use std::num::{Zero,One,ToStrRadix};

// FIXME #1284: handle complex NaN & infinity etc. This
// probably doesn't map to C's _Complex correctly.

// FIXME #5734:: Need generic sin/cos for .to/from_polar().
// FIXME #5735: Need generic sqrt to implement .norm().

/// A complex number in Cartesian form.
#[deriving(Eq,Clone)]
pub struct Complex<T> {
    /// Real portion of the complex number
    pub re: T,
    /// Imaginary portion of the complex number
    pub im: T
}

pub type Complex32 = Complex<f32>;
pub type Complex64 = Complex<f64>;

impl<T: Clone + Num> Complex<T> {
    /// Create a new Complex
    #[inline]
    pub fn new(re: T, im: T) -> Complex<T> {
        Complex { re: re, im: im }
    }

    /**
    Returns the square of the norm (since `T` doesn't necessarily
    have a sqrt function), i.e. `re^2 + im^2`.
    */
    #[inline]
    pub fn norm_sqr(&self) -> T {
        self.re * self.re + self.im * self.im
    }

    /// Returns the complex conjugate. i.e. `re - i im`
    #[inline]
    pub fn conj(&self) -> Complex<T> {
        Complex::new(self.re.clone(), -self.im)
    }

    /// Multiplies `self` by the scalar `t`.
    #[inline]
    pub fn scale(&self, t: T) -> Complex<T> {
        Complex::new(self.re * t, self.im * t)
    }

    /// Divides `self` by the scalar `t`.
    #[inline]
    pub fn unscale(&self, t: T) -> Complex<T> {
        Complex::new(self.re / t, self.im / t)
    }

    /// Returns `1/self`
    #[inline]
    pub fn inv(&self) -> Complex<T> {
        let norm_sqr = self.norm_sqr();
        Complex::new(self.re / norm_sqr,
                    -self.im / norm_sqr)
    }
}

impl<T: Clone + FloatMath> Complex<T> {
    /// Calculate |self|
    #[inline]
    pub fn norm(&self) -> T {
        self.re.hypot(self.im)
    }
}

impl<T: Clone + FloatMath> Complex<T> {
    /// Calculate the principal Arg of self.
    #[inline]
    pub fn arg(&self) -> T {
        self.im.atan2(self.re)
    }
    /// Convert to polar form (r, theta), such that `self = r * exp(i
    /// * theta)`
    #[inline]
    pub fn to_polar(&self) -> (T, T) {
        (self.norm(), self.arg())
    }
    /// Convert a polar representation into a complex number.
    #[inline]
    pub fn from_polar(r: &T, theta: &T) -> Complex<T> {
        Complex::new(*r * theta.cos(), *r * theta.sin())
    }
}

/* arithmetic */
// (a + i b) + (c + i d) == (a + c) + i (b + d)
impl<T: Clone + Num> Add<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn add(&self, other: &Complex<T>) -> Complex<T> {
        Complex::new(self.re + other.re, self.im + other.im)
    }
}
// (a + i b) - (c + i d) == (a - c) + i (b - d)
impl<T: Clone + Num> Sub<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn sub(&self, other: &Complex<T>) -> Complex<T> {
        Complex::new(self.re - other.re, self.im - other.im)
    }
}
// (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c)
impl<T: Clone + Num> Mul<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn mul(&self, other: &Complex<T>) -> Complex<T> {
        Complex::new(self.re*other.re - self.im*other.im,
                   self.re*other.im + self.im*other.re)
    }
}

// (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d)
//   == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)]
impl<T: Clone + Num> Div<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn div(&self, other: &Complex<T>) -> Complex<T> {
        let norm_sqr = other.norm_sqr();
        Complex::new((self.re*other.re + self.im*other.im) / norm_sqr,
                   (self.im*other.re - self.re*other.im) / norm_sqr)
    }
}

impl<T: Clone + Num> Neg<Complex<T>> for Complex<T> {
    #[inline]
    fn neg(&self) -> Complex<T> {
        Complex::new(-self.re, -self.im)
    }
}

/* constants */
impl<T: Clone + Num> Zero for Complex<T> {
    #[inline]
    fn zero() -> Complex<T> {
        Complex::new(Zero::zero(), Zero::zero())
    }

    #[inline]
    fn is_zero(&self) -> bool {
        self.re.is_zero() && self.im.is_zero()
    }
}

impl<T: Clone + Num> One for Complex<T> {
    #[inline]
    fn one() -> Complex<T> {
        Complex::new(One::one(), Zero::zero())
    }
}

/* string conversions */
impl<T: fmt::Show + Num + Ord> fmt::Show for Complex<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < Zero::zero() {
            write!(f, "{}-{}i", self.re, -self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}

impl<T: ToStrRadix + Num + Ord> ToStrRadix for Complex<T> {
    fn to_str_radix(&self, radix: uint) -> ~str {
        if self.im < Zero::zero() {
            format!("{}-{}i", self.re.to_str_radix(radix), (-self.im).to_str_radix(radix))
        } else {
            format!("{}+{}i", self.re.to_str_radix(radix), self.im.to_str_radix(radix))
        }
    }
}

#[cfg(test)]
mod test {
    #![allow(non_uppercase_statics)]

    use super::{Complex64, Complex};
    use std::num::{Zero,One,Float};

    pub static _0_0i : Complex64 = Complex { re: 0.0, im: 0.0 };
    pub static _1_0i : Complex64 = Complex { re: 1.0, im: 0.0 };
    pub static _1_1i : Complex64 = Complex { re: 1.0, im: 1.0 };
    pub static _0_1i : Complex64 = Complex { re: 0.0, im: 1.0 };
    pub static _neg1_1i : Complex64 = Complex { re: -1.0, im: 1.0 };
    pub static _05_05i : Complex64 = Complex { re: 0.5, im: 0.5 };
    pub static all_consts : [Complex64, .. 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i];

    #[test]
    fn test_consts() {
        // check our constants are what Complex::new creates
        fn test(c : Complex64, r : f64, i: f64) {
            assert_eq!(c, Complex::new(r,i));
        }
        test(_0_0i, 0.0, 0.0);
        test(_1_0i, 1.0, 0.0);
        test(_1_1i, 1.0, 1.0);
        test(_neg1_1i, -1.0, 1.0);
        test(_05_05i, 0.5, 0.5);

        assert_eq!(_0_0i, Zero::zero());
        assert_eq!(_1_0i, One::one());
    }

    #[test]
    #[ignore(cfg(target_arch = "x86"))]
    // FIXME #7158: (maybe?) currently failing on x86.
    fn test_norm() {
        fn test(c: Complex64, ns: f64) {
            assert_eq!(c.norm_sqr(), ns);
            assert_eq!(c.norm(), ns.sqrt())
        }
        test(_0_0i, 0.0);
        test(_1_0i, 1.0);
        test(_1_1i, 2.0);
        test(_neg1_1i, 2.0);
        test(_05_05i, 0.5);
    }

    #[test]
    fn test_scale_unscale() {
        assert_eq!(_05_05i.scale(2.0), _1_1i);
        assert_eq!(_1_1i.unscale(2.0), _05_05i);
        for &c in all_consts.iter() {
            assert_eq!(c.scale(2.0).unscale(2.0), c);
        }
    }

    #[test]
    fn test_conj() {
        for &c in all_consts.iter() {
            assert_eq!(c.conj(), Complex::new(c.re, -c.im));
            assert_eq!(c.conj().conj(), c);
        }
    }

    #[test]
    fn test_inv() {
        assert_eq!(_1_1i.inv(), _05_05i.conj());
        assert_eq!(_1_0i.inv(), _1_0i.inv());
    }

    #[test]
    #[should_fail]
    #[ignore]
    fn test_inv_zero() {
        // FIXME #5736: should this really fail, or just NaN?
        _0_0i.inv();
    }

    #[test]
    fn test_arg() {
        fn test(c: Complex64, arg: f64) {
            assert!((c.arg() - arg).abs() < 1.0e-6)
        }
        test(_1_0i, 0.0);
        test(_1_1i, 0.25 * Float::pi());
        test(_neg1_1i, 0.75 * Float::pi());
        test(_05_05i, 0.25 * Float::pi());
    }

    #[test]
    fn test_polar_conv() {
        fn test(c: Complex64) {
            let (r, theta) = c.to_polar();
            assert!((c - Complex::from_polar(&r, &theta)).norm() < 1e-6);
        }
        for &c in all_consts.iter() { test(c); }
    }

    mod arith {
        use super::{_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i, _05_05i, all_consts};
        use std::num::Zero;

        #[test]
        fn test_add() {
            assert_eq!(_05_05i + _05_05i, _1_1i);
            assert_eq!(_0_1i + _1_0i, _1_1i);
            assert_eq!(_1_0i + _neg1_1i, _0_1i);

            for &c in all_consts.iter() {
                assert_eq!(_0_0i + c, c);
                assert_eq!(c + _0_0i, c);
            }
        }

        #[test]
        fn test_sub() {
            assert_eq!(_05_05i - _05_05i, _0_0i);
            assert_eq!(_0_1i - _1_0i, _neg1_1i);
            assert_eq!(_0_1i - _neg1_1i, _1_0i);

            for &c in all_consts.iter() {
                assert_eq!(c - _0_0i, c);
                assert_eq!(c - c, _0_0i);
            }
        }

        #[test]
        fn test_mul() {
            assert_eq!(_05_05i * _05_05i, _0_1i.unscale(2.0));
            assert_eq!(_1_1i * _0_1i, _neg1_1i);

            // i^2 & i^4
            assert_eq!(_0_1i * _0_1i, -_1_0i);
            assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i);

            for &c in all_consts.iter() {
                assert_eq!(c * _1_0i, c);
                assert_eq!(_1_0i * c, c);
            }
        }
        #[test]
        fn test_div() {
            assert_eq!(_neg1_1i / _0_1i, _1_1i);
            for &c in all_consts.iter() {
                if c != Zero::zero() {
                    assert_eq!(c / c, _1_0i);
                }
            }
        }
        #[test]
        fn test_neg() {
            assert_eq!(-_1_0i + _0_1i, _neg1_1i);
            assert_eq!((-_0_1i) * _0_1i, _1_0i);
            for &c in all_consts.iter() {
                assert_eq!(-(-c), c);
            }
        }
    }

    #[test]
    fn test_to_str() {
        fn test(c : Complex64, s: StrBuf) {
            assert_eq!(c.to_str().to_strbuf(), s);
        }
        test(_0_0i, "0+0i".to_strbuf());
        test(_1_0i, "1+0i".to_strbuf());
        test(_0_1i, "0+1i".to_strbuf());
        test(_1_1i, "1+1i".to_strbuf());
        test(_neg1_1i, "-1+1i".to_strbuf());
        test(-_neg1_1i, "1-1i".to_strbuf());
        test(_05_05i, "0.5+0.5i".to_strbuf());
    }
}
<commit_msg>Remove two outdated FIXMEs from complex.rs<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Complex numbers.

use std::fmt;
use std::num::{Zero,One,ToStrRadix};

// FIXME #1284: handle complex NaN & infinity etc. This
// probably doesn't map to C's _Complex correctly.

/// A complex number in Cartesian form.
#[deriving(Eq,Clone)]
pub struct Complex<T> {
    /// Real portion of the complex number
    pub re: T,
    /// Imaginary portion of the complex number
    pub im: T
}

pub type Complex32 = Complex<f32>;
pub type Complex64 = Complex<f64>;

impl<T: Clone + Num> Complex<T> {
    /// Create a new Complex
    #[inline]
    pub fn new(re: T, im: T) -> Complex<T> {
        Complex { re: re, im: im }
    }

    /**
    Returns the square of the norm (since `T` doesn't necessarily
    have a sqrt function), i.e. `re^2 + im^2`.
    */
    #[inline]
    pub fn norm_sqr(&self) -> T {
        self.re * self.re + self.im * self.im
    }

    /// Returns the complex conjugate. i.e. `re - i im`
    #[inline]
    pub fn conj(&self) -> Complex<T> {
        Complex::new(self.re.clone(), -self.im)
    }

    /// Multiplies `self` by the scalar `t`.
    #[inline]
    pub fn scale(&self, t: T) -> Complex<T> {
        Complex::new(self.re * t, self.im * t)
    }

    /// Divides `self` by the scalar `t`.
    #[inline]
    pub fn unscale(&self, t: T) -> Complex<T> {
        Complex::new(self.re / t, self.im / t)
    }

    /// Returns `1/self`
    #[inline]
    pub fn inv(&self) -> Complex<T> {
        let norm_sqr = self.norm_sqr();
        Complex::new(self.re / norm_sqr,
                    -self.im / norm_sqr)
    }
}

impl<T: Clone + FloatMath> Complex<T> {
    /// Calculate |self|
    #[inline]
    pub fn norm(&self) -> T {
        self.re.hypot(self.im)
    }
}

impl<T: Clone + FloatMath> Complex<T> {
    /// Calculate the principal Arg of self.
    #[inline]
    pub fn arg(&self) -> T {
        self.im.atan2(self.re)
    }
    /// Convert to polar form (r, theta), such that `self = r * exp(i
    /// * theta)`
    #[inline]
    pub fn to_polar(&self) -> (T, T) {
        (self.norm(), self.arg())
    }
    /// Convert a polar representation into a complex number.
    #[inline]
    pub fn from_polar(r: &T, theta: &T) -> Complex<T> {
        Complex::new(*r * theta.cos(), *r * theta.sin())
    }
}

/* arithmetic */
// (a + i b) + (c + i d) == (a + c) + i (b + d)
impl<T: Clone + Num> Add<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn add(&self, other: &Complex<T>) -> Complex<T> {
        Complex::new(self.re + other.re, self.im + other.im)
    }
}
// (a + i b) - (c + i d) == (a - c) + i (b - d)
impl<T: Clone + Num> Sub<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn sub(&self, other: &Complex<T>) -> Complex<T> {
        Complex::new(self.re - other.re, self.im - other.im)
    }
}
// (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c)
impl<T: Clone + Num> Mul<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn mul(&self, other: &Complex<T>) -> Complex<T> {
        Complex::new(self.re*other.re - self.im*other.im,
                   self.re*other.im + self.im*other.re)
    }
}

// (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d)
//   == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)]
impl<T: Clone + Num> Div<Complex<T>, Complex<T>> for Complex<T> {
    #[inline]
    fn div(&self, other: &Complex<T>) -> Complex<T> {
        let norm_sqr = other.norm_sqr();
        Complex::new((self.re*other.re + self.im*other.im) / norm_sqr,
                   (self.im*other.re - self.re*other.im) / norm_sqr)
    }
}

impl<T: Clone + Num> Neg<Complex<T>> for Complex<T> {
    #[inline]
    fn neg(&self) -> Complex<T> {
        Complex::new(-self.re, -self.im)
    }
}

/* constants */
impl<T: Clone + Num> Zero for Complex<T> {
    #[inline]
    fn zero() -> Complex<T> {
        Complex::new(Zero::zero(), Zero::zero())
    }

    #[inline]
    fn is_zero(&self) -> bool {
        self.re.is_zero() && self.im.is_zero()
    }
}

impl<T: Clone + Num> One for Complex<T> {
    #[inline]
    fn one() -> Complex<T> {
        Complex::new(One::one(), Zero::zero())
    }
}

/* string conversions */
impl<T: fmt::Show + Num + Ord> fmt::Show for Complex<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < Zero::zero() {
            write!(f, "{}-{}i", self.re, -self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}

impl<T: ToStrRadix + Num + Ord> ToStrRadix for Complex<T> {
    fn to_str_radix(&self, radix: uint) -> ~str {
        if self.im < Zero::zero() {
            format!("{}-{}i", self.re.to_str_radix(radix), (-self.im).to_str_radix(radix))
        } else {
            format!("{}+{}i", self.re.to_str_radix(radix), self.im.to_str_radix(radix))
        }
    }
}

#[cfg(test)]
mod test {
    #![allow(non_uppercase_statics)]

    use super::{Complex64, Complex};
    use std::num::{Zero,One,Float};

    pub static _0_0i : Complex64 = Complex { re: 0.0, im: 0.0 };
    pub static _1_0i : Complex64 = Complex { re: 1.0, im: 0.0 };
    pub static _1_1i : Complex64 = Complex { re: 1.0, im: 1.0 };
    pub static _0_1i : Complex64 = Complex { re: 0.0, im: 1.0 };
    pub static _neg1_1i : Complex64 = Complex { re: -1.0, im: 1.0 };
    pub static _05_05i : Complex64 = Complex { re: 0.5, im: 0.5 };
    pub static all_consts : [Complex64, .. 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i];

    #[test]
    fn test_consts() {
        // check our constants are what Complex::new creates
        fn test(c : Complex64, r : f64, i: f64) {
            assert_eq!(c, Complex::new(r,i));
        }
        test(_0_0i, 0.0, 0.0);
        test(_1_0i, 1.0, 0.0);
        test(_1_1i, 1.0, 1.0);
        test(_neg1_1i, -1.0, 1.0);
        test(_05_05i, 0.5, 0.5);

        assert_eq!(_0_0i, Zero::zero());
        assert_eq!(_1_0i, One::one());
    }

    #[test]
    #[ignore(cfg(target_arch = "x86"))]
    // FIXME #7158: (maybe?) currently failing on x86.
    fn test_norm() {
        fn test(c: Complex64, ns: f64) {
            assert_eq!(c.norm_sqr(), ns);
            assert_eq!(c.norm(), ns.sqrt())
        }
        test(_0_0i, 0.0);
        test(_1_0i, 1.0);
        test(_1_1i, 2.0);
        test(_neg1_1i, 2.0);
        test(_05_05i, 0.5);
    }

    #[test]
    fn test_scale_unscale() {
        assert_eq!(_05_05i.scale(2.0), _1_1i);
        assert_eq!(_1_1i.unscale(2.0), _05_05i);
        for &c in all_consts.iter() {
            assert_eq!(c.scale(2.0).unscale(2.0), c);
        }
    }

    #[test]
    fn test_conj() {
        for &c in all_consts.iter() {
            assert_eq!(c.conj(), Complex::new(c.re, -c.im));
            assert_eq!(c.conj().conj(), c);
        }
    }

    #[test]
    fn test_inv() {
        assert_eq!(_1_1i.inv(), _05_05i.conj());
        assert_eq!(_1_0i.inv(), _1_0i.inv());
    }

    #[test]
    #[should_fail]
    #[ignore]
    fn test_inv_zero() {
        // FIXME #5736: should this really fail, or just NaN?
        _0_0i.inv();
    }

    #[test]
    fn test_arg() {
        fn test(c: Complex64, arg: f64) {
            assert!((c.arg() - arg).abs() < 1.0e-6)
        }
        test(_1_0i, 0.0);
        test(_1_1i, 0.25 * Float::pi());
        test(_neg1_1i, 0.75 * Float::pi());
        test(_05_05i, 0.25 * Float::pi());
    }

    #[test]
    fn test_polar_conv() {
        fn test(c: Complex64) {
            let (r, theta) = c.to_polar();
            assert!((c - Complex::from_polar(&r, &theta)).norm() < 1e-6);
        }
        for &c in all_consts.iter() { test(c); }
    }

    mod arith {
        use super::{_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i, _05_05i, all_consts};
        use std::num::Zero;

        #[test]
        fn test_add() {
            assert_eq!(_05_05i + _05_05i, _1_1i);
            assert_eq!(_0_1i + _1_0i, _1_1i);
            assert_eq!(_1_0i + _neg1_1i, _0_1i);

            for &c in all_consts.iter() {
                assert_eq!(_0_0i + c, c);
                assert_eq!(c + _0_0i, c);
            }
        }

        #[test]
        fn test_sub() {
            assert_eq!(_05_05i - _05_05i, _0_0i);
            assert_eq!(_0_1i - _1_0i, _neg1_1i);
            assert_eq!(_0_1i - _neg1_1i, _1_0i);

            for &c in all_consts.iter() {
                assert_eq!(c - _0_0i, c);
                assert_eq!(c - c, _0_0i);
            }
        }

        #[test]
        fn test_mul() {
            assert_eq!(_05_05i * _05_05i, _0_1i.unscale(2.0));
            assert_eq!(_1_1i * _0_1i, _neg1_1i);

            // i^2 & i^4
            assert_eq!(_0_1i * _0_1i, -_1_0i);
            assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i);

            for &c in all_consts.iter() {
                assert_eq!(c * _1_0i, c);
                assert_eq!(_1_0i * c, c);
            }
        }
        #[test]
        fn test_div() {
            assert_eq!(_neg1_1i / _0_1i, _1_1i);
            for &c in all_consts.iter() {
                if c != Zero::zero() {
                    assert_eq!(c / c, _1_0i);
                }
            }
        }
        #[test]
        fn test_neg() {
            assert_eq!(-_1_0i + _0_1i, _neg1_1i);
            assert_eq!((-_0_1i) * _0_1i, _1_0i);
            for &c in all_consts.iter() {
                assert_eq!(-(-c), c);
            }
        }
    }

    #[test]
    fn test_to_str() {
        fn test(c : Complex64, s: StrBuf) {
            assert_eq!(c.to_str().to_strbuf(), s);
        }
        test(_0_0i, "0+0i".to_strbuf());
        test(_1_0i, "1+0i".to_strbuf());
        test(_0_1i, "0+1i".to_strbuf());
        test(_1_1i, "1+1i".to_strbuf());
        test(_neg1_1i, "-1+1i".to_strbuf());
        test(-_neg1_1i, "1-1i".to_strbuf());
        test(_05_05i, "0.5+0.5i".to_strbuf());
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 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.

//! Networking primitives for TCP/UDP communication.

#![stable(feature = "rust1", since = "1.0.0")]

use prelude::v1::*;

use io::{self, Error, ErrorKind};
use sys_common::net as net_imp;

pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
pub use self::tcp::{TcpStream, TcpListener};
pub use self::udp::UdpSocket;
pub use self::parser::AddrParseError;

mod ip;
mod addr;
mod tcp;
mod udp;
mod parser;
#[cfg(test)] mod test;

/// Possible values which can be passed to the `shutdown` method of `TcpStream`
/// and `UdpSocket`.
#[derive(Copy, Clone, PartialEq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Shutdown {
    /// Indicates that the reading portion of this stream/socket should be shut
    /// down. All currently blocked and future reads will return `Ok(0)`.
    #[stable(feature = "rust1", since = "1.0.0")]
    Read,
    /// Indicates that the writing portion of this stream/socket should be shut
    /// down. All currently blocked and future writes will return an error.
    #[stable(feature = "rust1", since = "1.0.0")]
    Write,
    /// Shut down both the reading and writing portions of this stream.
    ///
    /// See `Shutdown::Read` and `Shutdown::Write` for more information.
    #[stable(feature = "rust1", since = "1.0.0")]
    Both,
}

#[doc(hidden)]
trait NetInt {
    fn from_be(i: Self) -> Self;
    fn to_be(&self) -> Self;
}
macro_rules! doit {
    ($($t:ident)*) => ($(impl NetInt for $t {
        fn from_be(i: Self) -> Self { <$t>::from_be(i) }
        fn to_be(&self) -> Self { <$t>::to_be(*self) }
    })*)
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }

fn hton<I: NetInt>(i: I) -> I { i.to_be() }
fn ntoh<I: NetInt>(i: I) -> I { I::from_be(i) }

fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
    where F: FnMut(&SocketAddr) -> io::Result<T>
{
    let mut last_err = None;
    for addr in try!(addr.to_socket_addrs()) {
        match f(&addr) {
            Ok(l) => return Ok(l),
            Err(e) => last_err = Some(e),
        }
    }
    Err(last_err.unwrap_or_else(|| {
        Error::new(ErrorKind::InvalidInput,
                   "could not resolve to any addresses")
    }))
}

/// An iterator over `SocketAddr` values returned from a host lookup operation.
#[unstable(feature = "lookup_host", reason = "unsure about the returned \
                                              iterator and returning socket \
                                              addresses")]
pub struct LookupHost(net_imp::LookupHost);

#[unstable(feature = "lookup_host", reason = "unsure about the returned \
                                              iterator and returning socket \
                                              addresses")]
impl Iterator for LookupHost {
    type Item = io::Result<SocketAddr>;
    fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() }
}

/// Resolve the host specified by `host` as a number of `SocketAddr` instances.
///
/// This method may perform a DNS query to resolve `host` and may also inspect
/// system configuration to resolve the specified hostname.
///
/// # Examples
///
/// ```no_run
/// # #![feature(lookup_host)]
/// use std::net;
///
/// # fn foo() -> std::io::Result<()> {
/// for host in try!(net::lookup_host("rust-lang.org")) {
///     println!("found address: {}", try!(host));
/// }
/// # Ok(())
/// # }
/// ```
#[unstable(feature = "lookup_host", reason = "unsure about the returned \
                                              iterator and returning socket \
                                              addresses")]
pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
    net_imp::lookup_host(host).map(LookupHost)
}

/// Resolve the given address to a hostname.
///
/// This function may perform a DNS query to resolve `addr` and may also inspect
/// system configuration to resolve the specified address. If the address
/// cannot be resolved, it is returned in string format.
#[unstable(feature = "lookup_addr", reason = "recent addition")]
pub fn lookup_addr(addr: &IpAddr) -> io::Result<String> {
    net_imp::lookup_addr(addr)
}
<commit_msg>std: Reexport std::net::tcp::Incoming<commit_after>// Copyright 2015 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.

//! Networking primitives for TCP/UDP communication.

#![stable(feature = "rust1", since = "1.0.0")]

use prelude::v1::*;

use io::{self, Error, ErrorKind};
use sys_common::net as net_imp;

pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
pub use self::tcp::{TcpStream, TcpListener, Incoming};
pub use self::udp::UdpSocket;
pub use self::parser::AddrParseError;

mod ip;
mod addr;
mod tcp;
mod udp;
mod parser;
#[cfg(test)] mod test;

/// Possible values which can be passed to the `shutdown` method of `TcpStream`
/// and `UdpSocket`.
#[derive(Copy, Clone, PartialEq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Shutdown {
    /// Indicates that the reading portion of this stream/socket should be shut
    /// down. All currently blocked and future reads will return `Ok(0)`.
    #[stable(feature = "rust1", since = "1.0.0")]
    Read,
    /// Indicates that the writing portion of this stream/socket should be shut
    /// down. All currently blocked and future writes will return an error.
    #[stable(feature = "rust1", since = "1.0.0")]
    Write,
    /// Shut down both the reading and writing portions of this stream.
    ///
    /// See `Shutdown::Read` and `Shutdown::Write` for more information.
    #[stable(feature = "rust1", since = "1.0.0")]
    Both,
}

#[doc(hidden)]
trait NetInt {
    fn from_be(i: Self) -> Self;
    fn to_be(&self) -> Self;
}
macro_rules! doit {
    ($($t:ident)*) => ($(impl NetInt for $t {
        fn from_be(i: Self) -> Self { <$t>::from_be(i) }
        fn to_be(&self) -> Self { <$t>::to_be(*self) }
    })*)
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }

fn hton<I: NetInt>(i: I) -> I { i.to_be() }
fn ntoh<I: NetInt>(i: I) -> I { I::from_be(i) }

fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
    where F: FnMut(&SocketAddr) -> io::Result<T>
{
    let mut last_err = None;
    for addr in try!(addr.to_socket_addrs()) {
        match f(&addr) {
            Ok(l) => return Ok(l),
            Err(e) => last_err = Some(e),
        }
    }
    Err(last_err.unwrap_or_else(|| {
        Error::new(ErrorKind::InvalidInput,
                   "could not resolve to any addresses")
    }))
}

/// An iterator over `SocketAddr` values returned from a host lookup operation.
#[unstable(feature = "lookup_host", reason = "unsure about the returned \
                                              iterator and returning socket \
                                              addresses")]
pub struct LookupHost(net_imp::LookupHost);

#[unstable(feature = "lookup_host", reason = "unsure about the returned \
                                              iterator and returning socket \
                                              addresses")]
impl Iterator for LookupHost {
    type Item = io::Result<SocketAddr>;
    fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() }
}

/// Resolve the host specified by `host` as a number of `SocketAddr` instances.
///
/// This method may perform a DNS query to resolve `host` and may also inspect
/// system configuration to resolve the specified hostname.
///
/// # Examples
///
/// ```no_run
/// # #![feature(lookup_host)]
/// use std::net;
///
/// # fn foo() -> std::io::Result<()> {
/// for host in try!(net::lookup_host("rust-lang.org")) {
///     println!("found address: {}", try!(host));
/// }
/// # Ok(())
/// # }
/// ```
#[unstable(feature = "lookup_host", reason = "unsure about the returned \
                                              iterator and returning socket \
                                              addresses")]
pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
    net_imp::lookup_host(host).map(LookupHost)
}

/// Resolve the given address to a hostname.
///
/// This function may perform a DNS query to resolve `addr` and may also inspect
/// system configuration to resolve the specified address. If the address
/// cannot be resolved, it is returned in string format.
#[unstable(feature = "lookup_addr", reason = "recent addition")]
pub fn lookup_addr(addr: &IpAddr) -> io::Result<String> {
    net_imp::lookup_addr(addr)
}
<|endoftext|>


<commit_before>// Copyright 2013-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.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(unix, not(target_os = "ios"))]
mod imp {
    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::{Ok, Err};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    #[cfg(unix)]
    pub struct OsRng {
        inner: ReaderRng<File>
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: reader_rng })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            self.inner.next_u32()
        }
        fn next_u64(&mut self) -> u64 {
            self.inner.next_u64()
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            self.inner.fill_bytes(v)
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use collections::Collection;
    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::MutableSlice;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        marker: marker::NoCopy
    }

    #[repr(C)]
    struct SecRandom;

    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng {marker: marker::NoCopy} )
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use core_collections::Collection;
    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::MutableSlice;

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                fail!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<commit_msg>Fix libstd<commit_after>// Copyright 2013-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.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::{Ok, Err};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    #[cfg(unix)]
    pub struct OsRng {
        inner: ReaderRng<File>
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: reader_rng })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            self.inner.next_u32()
        }
        fn next_u64(&mut self) -> u64 {
            self.inner.next_u64()
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            self.inner.fill_bytes(v)
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use collections::Collection;
    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::MutableSlice;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        marker: marker::NoCopy
    }

    #[repr(C)]
    struct SecRandom;

    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng {marker: marker::NoCopy} )
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use core_collections::Collection;
    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::MutableSlice;

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                fail!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<|endoftext|>


<commit_before>use matching::fragment;
use matching::fragment::Fragment;
use std::path::PathBuf;
use std::collections::hash_map::HashMap;

#[derive(PartialEq)]
pub struct Entry {
    pub path: PathBuf,
    pub index: HashMap<char, Vec<usize>>,
}

impl Entry {
    /// Compares the query string to the entry,
    /// and returns a score between 0 and 1.
    pub fn similarity(&self, query: &str) -> f32 {
        // Exact matches produce a perfect score.
        if query == self.path.to_string_lossy() {
            return 1.0;
        }

        // Pre-calculate the path length as we'll be using it frequently.
        let path_length = self.path.to_string_lossy().chars().count();

        // We track fragment/substring matches, which have a greater weight than
        // a simple sum of individual character occurrences in the entry path.
        let mut match_fragments: Vec<Fragment> = Vec::new();

        // This counter is used to track characters in the query that aren't in
        // the entry's path, which has discrete weighting in the final score.
        let mut non_existent_char_count = 0;

        // Look for the query's character in the path's index, bumping
        // the character score up for each occurrence in the path.
        for query_char in query.chars() {
            match self.index.get(&query_char) {
                Some(occurrences) => {
                    // Initially, we'll assume that none of the occurrences
                    // of this character have been tracked as fragments.
                    let mut unaccounted_occurrences = occurrences.clone();

                    // Extend any existing fragment matches that also
                    // have this char at the end of their existing match.
                    for fragment in match_fragments.iter_mut() {
                        // Get the index at which this character would have to
                        // occur to extend this particular fragment over it.
                        let target_index = fragment.next_index();

                        if occurrences.contains(&target_index) {
                            // Since this character match is covered by this
                            // fragment, remove it from the unaccounted set.
                            match unaccounted_occurrences.iter().position(|&o| o == target_index) {
                                Some(position) => {
                                    unaccounted_occurrences.remove(position);
                                },
                                None => (),
                            }

                            // Bump the fragment's length to cover this char.
                            fragment.increase_length();
                        }
                    }

                    // Create fragment matches for any unaccounted occurrences.
                    for occurrence_index in unaccounted_occurrences.iter() {
                        match_fragments.push(fragment::new(*occurrence_index));
                    }

                },
                None => {
                    // Characters in the query string that
                    // aren't in the path reduce the score;
                    // track these so we can consider them later.
                    non_existent_char_count += 1;
                },
            }
        }

        // Determine the percentage of characters in the query string that
        // are in the entry, using the non-existent count we've calculated.
        let non_existence_penalty = (
            path_length - non_existent_char_count) as f32 / path_length as f32;

        // Calculate an exponentially-scaled score based on fragment lengths.
        let fragment_score = match_fragments.iter().fold(0, |acc, ref fragment| {
            acc + fragment.length.pow(2)
        });

        // Calculate and return the similarity value. The path_length division
        // is used to offset the increased fragment score probability for
        // larger entry paths.
        fragment_score as f32 * non_existence_penalty / path_length as f32
    }
}

fn index_path(path: &str) -> HashMap<char, Vec<usize>> {
    let mut index: HashMap<char, Vec<usize>> = HashMap::new();
    for (char_index, path_char) in path.chars().enumerate() {
        if index.contains_key(&path_char) {
            match index.get_mut(&path_char) {
               Some(occurrences) => occurrences.push(char_index),
               None => ()
            }
        } else {
           index.insert(path_char, vec![char_index]);
        }
    }

    index
}

pub fn new(path: String) -> Entry {
    Entry{
        // Build the index before we transfer ownership of path.
        index: index_path(&path),
        path: PathBuf::from(path),
    }
}

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

    #[test]
    fn similarity_correctly_scores_perfect_matches() {
        let entry = new("src/hound.rs".to_string());
        assert_eq!(entry.similarity("src/hound.rs"), 1.0);
    }

    #[test]
    fn similarity_correctly_scores_completely_different_terms() {
        let entry = new("src".to_string());
        assert_eq!(entry.similarity("lib"), 0.0);
    }

    #[test]
    fn similarity_scores_based_on_term_length() {
        let long_entry = new("hound library".to_string());
        let differing_length_score = long_entry.similarity("houn");

        // Don't use a perfect match, since those product a perfect score.
        let short_entry = new("hound".to_string());
        let same_length_score = short_entry.similarity("houn");

        assert!(same_length_score > differing_length_score);
    }

    #[test]
    fn similarity_score_increases_for_consecutive_matches() {
        let entry = new("hound".to_string());

        // Don't use a perfect match, since those product a perfect score.
        let properly_ordered_score = entry.similarity(" houn");

        let improperly_ordered_score = entry.similarity("nuoh");
        assert!(properly_ordered_score > improperly_ordered_score);
    }

    #[test]
    fn similarity_score_decreases_for_non_matching_characters() {
        let entry = new("hound".to_string());

        // Don't use a perfect match, since those product a perfect score.
        let non_matching_score = entry.similarity("houns");

        let subset_score = entry.similarity("houn");
        assert!(subset_score > non_matching_score);
    }
}
<commit_msg>Avoid arithmetic overflow when calculating penalty.<commit_after>use matching::fragment;
use matching::fragment::Fragment;
use std::path::PathBuf;
use std::collections::hash_map::HashMap;

#[derive(PartialEq)]
pub struct Entry {
    pub path: PathBuf,
    pub index: HashMap<char, Vec<usize>>,
}

impl Entry {
    /// Compares the query string to the entry,
    /// and returns a score between 0 and 1.
    pub fn similarity(&self, query: &str) -> f32 {
        // Exact matches produce a perfect score.
        if query == self.path.to_string_lossy() {
            return 1.0;
        }

        // Pre-calculate the path length as we'll be using it frequently.
        let path_length = self.path.to_string_lossy().chars().count();

        // We track fragment/substring matches, which have a greater weight than
        // a simple sum of individual character occurrences in the entry path.
        let mut match_fragments: Vec<Fragment> = Vec::new();

        // This counter is used to track characters in the query that aren't in
        // the entry's path, which has discrete weighting in the final score.
        let mut non_existent_char_count = 0;

        // Look for the query's character in the path's index, bumping
        // the character score up for each occurrence in the path.
        for query_char in query.chars() {
            match self.index.get(&query_char) {
                Some(occurrences) => {
                    // Initially, we'll assume that none of the occurrences
                    // of this character have been tracked as fragments.
                    let mut unaccounted_occurrences = occurrences.clone();

                    // Extend any existing fragment matches that also
                    // have this char at the end of their existing match.
                    for fragment in match_fragments.iter_mut() {
                        // Get the index at which this character would have to
                        // occur to extend this particular fragment over it.
                        let target_index = fragment.next_index();

                        if occurrences.contains(&target_index) {
                            // Since this character match is covered by this
                            // fragment, remove it from the unaccounted set.
                            match unaccounted_occurrences.iter().position(|&o| o == target_index) {
                                Some(position) => {
                                    unaccounted_occurrences.remove(position);
                                },
                                None => (),
                            }

                            // Bump the fragment's length to cover this char.
                            fragment.increase_length();
                        }
                    }

                    // Create fragment matches for any unaccounted occurrences.
                    for occurrence_index in unaccounted_occurrences.iter() {
                        match_fragments.push(fragment::new(*occurrence_index));
                    }

                },
                None => {
                    // Characters in the query string that
                    // aren't in the path reduce the score;
                    // track these so we can consider them later.
                    non_existent_char_count += 1;
                },
            }
        }

        // Determine the percentage of characters in the query string that
        // are in the entry, using the non-existent count we've calculated.
        let non_existence_penalty =
            // Guard against a potential arithmetic overflow here.
            if non_existent_char_count >= path_length {
                return 0.0f32
            } else {
                (path_length - non_existent_char_count) as f32 / path_length as f32
            };

        // Calculate an exponentially-scaled score based on fragment lengths.
        let fragment_score = match_fragments.iter().fold(0, |acc, ref fragment| {
            acc + fragment.length.pow(2)
        });

        // Calculate and return the similarity value. The path_length division
        // is used to offset the increased fragment score probability for
        // larger entry paths.
        fragment_score as f32 * non_existence_penalty / path_length as f32
    }
}

fn index_path(path: &str) -> HashMap<char, Vec<usize>> {
    let mut index: HashMap<char, Vec<usize>> = HashMap::new();
    for (char_index, path_char) in path.chars().enumerate() {
        if index.contains_key(&path_char) {
            match index.get_mut(&path_char) {
               Some(occurrences) => occurrences.push(char_index),
               None => ()
            }
        } else {
           index.insert(path_char, vec![char_index]);
        }
    }

    index
}

pub fn new(path: String) -> Entry {
    Entry{
        // Build the index before we transfer ownership of path.
        index: index_path(&path),
        path: PathBuf::from(path),
    }
}

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

    #[test]
    fn similarity_correctly_scores_perfect_matches() {
        let entry = new("src/hound.rs".to_string());
        assert_eq!(entry.similarity("src/hound.rs"), 1.0);
    }

    #[test]
    fn similarity_correctly_scores_completely_different_terms() {
        let entry = new("src".to_string());
        assert_eq!(entry.similarity("lib"), 0.0);
    }

    #[test]
    fn similarity_scores_based_on_term_length() {
        let long_entry = new("hound library".to_string());
        let differing_length_score = long_entry.similarity("houn");

        // Don't use a perfect match, since those product a perfect score.
        let short_entry = new("hound".to_string());
        let same_length_score = short_entry.similarity("houn");

        assert!(same_length_score > differing_length_score);
    }

    #[test]
    fn similarity_score_increases_for_consecutive_matches() {
        let entry = new("hound".to_string());

        // Don't use a perfect match, since those product a perfect score.
        let properly_ordered_score = entry.similarity(" houn");

        let improperly_ordered_score = entry.similarity("nuoh");
        assert!(properly_ordered_score > improperly_ordered_score);
    }

    #[test]
    fn similarity_score_decreases_for_non_matching_characters() {
        let entry = new("hound".to_string());

        // Don't use a perfect match, since those product a perfect score.
        let non_matching_score = entry.similarity("houns");

        let subset_score = entry.similarity("houn");
        assert!(subset_score > non_matching_score);
    }

    #[test]
    fn similarity_score_is_zero_for_larger_query_with_no_matching_characters() {
        let entry = new("amp".to_string());
        assert_eq!(entry.similarity("hound"), 0.0f32);
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-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.

// ignore-pretty very bad with line comments

extern crate sync;

use std::io;
use sync::Future;

static ITER: int = 50;
static LIMIT: f64 = 2.0;

fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) {
    for chunk_init_r in vec_init_r.chunks(8) {
        let mut cur_byte = 0xff;
        let mut cur_bitmask = 0x80;
        for &init_r in chunk_init_r.iter() {
            let mut cur_r = init_r;
            let mut cur_i = init_i;
            for _ in range(0, ITER) {
                let r = cur_r;
                let i = cur_i;
                cur_r = r * r - i * i + init_r;
                cur_i = 2.0 * r * i + init_i;

                if r * r + i * i > LIMIT * LIMIT {
                    cur_byte &= !cur_bitmask;
                    break;
                }
            }
            cur_bitmask >>= 1;
        }
        res.push(cur_byte);
    }
}

fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
    // Ensure w and h are multiples of 8.
    let w = (w + 7) / 8 * 8;
    let h = w;
    let chunk_size = h / 8;

    let data: Vec<Future<Vec<u8>>> = range(0u, 8).map(|i| Future::spawn(proc () {
        let vec_init_r = Vec::from_fn(w, |x| 2.0 * (x as f64) / (w as f64) - 1.5);
        let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
        for y in range(i * chunk_size, (i + 1) * chunk_size) {
            let init_i = 2.0 * (y as f64) / (h as f64) - 1.0;
            write_line(init_i, vec_init_r.as_slice(), &mut res);
        }
        res
    })).collect();

    try!(writeln!(&mut out as &mut Writer, "P4\n{} {}", w, h));
    for res in data.move_iter() {
        try!(out.write(res.unwrap().as_slice()));
    }
    out.flush()
}

fn main() {
    let args = std::os::args();
    let args = args.as_slice();
    let res = if args.len() < 2 {
        println!("Test mode: do not dump the image because it's not utf8, \
                  which interferes with the test runner.");
        mandelbrot(1000, std::io::util::NullWriter)
    } else {
        mandelbrot(from_str(args[1]).unwrap(), std::io::stdout())
    };
    res.unwrap();
}
<commit_msg>shootout-mandlebrot: calculate two bits of the result per inner loop, +10-15%<commit_after>// Copyright 2012-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.
#![feature(macro_rules)]

// ignore-pretty very bad with line comments

extern crate sync;

use std::io;
use sync::Future;

static ITER: int = 50;
static LIMIT: f64 = 2.0;

macro_rules! core_loop(
    ($pow:expr ~ $mask:expr: $ctx:ident, $b:ident) => (
        {
            let r = $ctx.r;
            let i = $ctx.i;

            $ctx.r = r * r - i * i + $ctx.init_r;
            $ctx.i = 2.0 * r * i + $ctx.init_i;

            if r * r + i * i > LIMIT * LIMIT {
                $b |= $pow;
                if $b == $mask { break; }
            }
        }
    );
)

#[inline(always)]
fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) {
    struct Context { r: f64, i: f64, init_i: f64, init_r: f64 }
    impl Context {
        #[inline(always)]
        fn new(i: f64, r: f64) -> Context {
            Context { r: r, i: i, init_r: r, init_i: i }
        }
    }

    let mut cur_byte;
    let mut i;
    let mut bit_1;
    let mut bit_2;
    let mut b;
    for chunk_init_r in vec_init_r.chunks(8) {
        cur_byte = 0xff;
        i = 0;

        while i < 8 {
            bit_1 = Context::new(init_i, chunk_init_r[i]);
            bit_2 = Context::new(init_i, chunk_init_r[i + 1]);

            b = 0;
            for _ in range(0, ITER) {
                core_loop!(2 ~ 3: bit_1, b);
                core_loop!(1 ~ 3: bit_2, b);
            }

            cur_byte = (cur_byte << 2) + b;
            i += 2;
        }
        res.push(cur_byte^-1);
    }
}

fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
    // Ensure w and h are multiples of 8.
    let w = (w + 7) / 8 * 8;
    let h = w;
    let inverse_w_doubled = 2.0 / w as f64;
    let inverse_h_doubled = 2.0 / h as f64;
    let chunk_size = h / 16;

    let data: Vec<Future<Vec<u8>>> = range(0u, 16).map(|i| Future::spawn(proc () {
        let vec_init_r = Vec::from_fn(w, |x| (x as f64) * inverse_w_doubled - 1.5);
        let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
        for y in range(i * chunk_size, (i + 1) * chunk_size) {
            let init_i = (y as f64) * inverse_h_doubled - 1.0;
            write_line(init_i, vec_init_r.as_slice(), &mut res);
        }
        res
    })).collect();

    try!(writeln!(&mut out as &mut Writer, "P4\n{} {}", w, h));
    for res in data.move_iter() {
        try!(out.write(res.unwrap().as_slice()));
    }
    out.flush()
}

fn main() {
    let args = std::os::args();
    let args = args.as_slice();
    let res = if args.len() < 2 {
        println!("Test mode: do not dump the image because it's not utf8, \
                  which interferes with the test runner.");
        mandelbrot(1000, std::io::util::NullWriter)
    } else {
        mandelbrot(from_str(args[1]).unwrap(), std::io::stdout())
    };
    res.unwrap();
}
<|endoftext|>


<commit_before>// Basic test for free regions in the NLL code. This test does not
// report an error because of the (implied) bound that `'b: 'a`.

// compile-flags:-Zborrowck=mir -Zverbose
// compile-pass

#![allow(warnings)]

fn foo<'a, 'b>(x: &'a &'b u32) -> &'a u32 {
    &**x
}

fn main() { }
<commit_msg>Rollup merge of #60648 - petrochenkov:shorten2, r=Dylan-DPC<commit_after>// Basic test for free regions in the NLL code. This test does not
// report an error because of the (implied) bound that `'b: 'a`.

// compile-flags:-Zborrowck=mir -Zverbose
// compile-pass
// skip-codegen

fn foo<'a, 'b>(x: &'a &'b u32) -> &'a u32 {
    &**x
}

fn main() { }
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::{lsp_runtime_error::LSPRuntimeResult, server::LSPState};
use common::PerfLogger;
use lsp_types::request::Request;
use schema_documentation::SchemaDocumentation;
use serde::{Deserialize, Serialize};

pub(crate) enum SearchSchemaItems {}

#[derive(Deserialize, Serialize)]
pub(crate) struct SchemaSearchItemsResponse {
    pub items: Vec<()>,
}

#[derive(Deserialize, Serialize)]
pub(crate) struct SearchSchemaItemsParams {
    pub filter: Option<String>,
    pub schema_name: String,
    pub take: Option<usize>,
    pub skip: Option<usize>,
}

impl Request for SearchSchemaItems {
    type Params = SearchSchemaItemsParams;
    type Result = SchemaSearchItemsResponse;
    const METHOD: &'static str = "relay/searchSchemaItems";
}

pub(crate) fn on_search_schema_items<
    TPerfLogger: PerfLogger + 'static,
    TSchemaDocumentation: SchemaDocumentation,
>(
    _state: &mut LSPState<TPerfLogger, TSchemaDocumentation>,
    _params: SearchSchemaItemsParams,
) -> LSPRuntimeResult<<SearchSchemaItems as Request>::Result> {
    let items = vec![];

    Ok(SchemaSearchItemsResponse { items })
}
<commit_msg>Re-enable on_search_schema_items<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::{
    lsp_runtime_error::{LSPRuntimeError, LSPRuntimeResult},
    server::LSPState,
};
use common::{Named, PerfLogger};
use interner::Intern;
use lsp_types::request::Request;
use schema::Schema;
use schema_documentation::SchemaDocumentation;
use serde::{Deserialize, Serialize};

pub(crate) enum SearchSchemaItems {}

#[derive(Deserialize, Serialize)]
pub(crate) struct TypeDescription {
    name: String,
    description: Option<String>,
}

#[derive(Deserialize, Serialize)]
pub(crate) struct SchemaSearchItemsResponse {
    pub items: Vec<TypeDescription>,
}

#[derive(Deserialize, Serialize)]
pub(crate) struct SearchSchemaItemsParams {
    pub filter: Option<String>,
    pub schema_name: String,
    pub take: Option<usize>,
    pub skip: Option<usize>,
}

impl Request for SearchSchemaItems {
    type Params = SearchSchemaItemsParams;
    type Result = SchemaSearchItemsResponse;
    const METHOD: &'static str = "relay/searchSchemaItems";
}

pub(crate) fn on_search_schema_items<
    TPerfLogger: PerfLogger + 'static,
    TSchemaDocumentation: SchemaDocumentation,
>(
    state: &mut LSPState<TPerfLogger, TSchemaDocumentation>,
    params: SearchSchemaItemsParams,
) -> LSPRuntimeResult<<SearchSchemaItems as Request>::Result> {
    let filter = params.filter.map(|f| f.to_lowercase());
    let schema_name: &str = &params.schema_name;
    let schemas = state.get_schemas();
    let schema = schemas
        .get(&schema_name.intern())
        .ok_or(LSPRuntimeError::ExpectedError)?;
    let schema_documentation = state.get_schema_documentation(schema_name);

    let objects = filter_and_transform_items(schema.objects(), &schema_documentation, &filter);
    let interfaces =
        filter_and_transform_items(schema.interfaces(), &schema_documentation, &filter);
    let enums = filter_and_transform_items(schema.enums(), &schema_documentation, &filter);
    let unions = filter_and_transform_items(schema.unions(), &schema_documentation, &filter);
    let input_objects =
        filter_and_transform_items(schema.input_objects(), &schema_documentation, &filter);
    let scalars = filter_and_transform_items(schema.scalars(), &schema_documentation, &filter);

    let items = objects
        .chain(interfaces)
        .chain(enums)
        .chain(unions)
        .chain(input_objects)
        .chain(scalars)
        .skip(*params.skip.as_ref().unwrap_or(&0))
        .take(*params.take.as_ref().unwrap_or(&500))
        .collect::<Vec<_>>();

    Ok(SchemaSearchItemsResponse { items })
}

fn filter_and_transform_items<'a, T: Named + 'a>(
    items: impl Iterator<Item = &'a T> + 'a,
    schema_documentation: &'a impl SchemaDocumentation,
    filter: &'a Option<String>,
) -> impl Iterator<Item = TypeDescription> + 'a {
    items.filter_map(move |obj| {
        let name = obj.name().lookup();
        let description = schema_documentation
            .get_type_description(name)
            .map(|s| s.to_string());

        if should_include_named_item(name, &description, filter) {
            Some(TypeDescription {
                name: name.to_string(),
                description,
            })
        } else {
            None
        }
    })
}

fn should_include_named_item(
    name: &str,
    description: &Option<String>,
    filter: &Option<String>,
) -> bool {
    if let Some(filter) = filter.as_ref() {
        if name.to_lowercase().contains(filter) {
            true
        } else if let Some(description) = description {
            description.to_lowercase().contains(filter)
        } else {
            false
        }
    } else {
        true
    }
}

#[cfg(test)]
mod tests {
    use crate::search_schema_items::should_include_named_item;

    #[test]
    fn test_no_filter() {
        assert_eq!(
            should_include_named_item("Yohan Blake", &Some("London 2012".to_string()), &None),
            true
        );
        assert_eq!(should_include_named_item("Usain Bolt", &None, &None), true);
    }

    #[test]
    fn test_filter_matches_name() {
        assert_eq!(
            should_include_named_item("Michael Frater", &None, &Some("michael".to_string())),
            true
        );
        assert_eq!(
            should_include_named_item(
                "Nesta Carter",
                &Some("London 2012".to_string()),
                &Some("nesta".to_string())
            ),
            true
        );
    }

    #[test]
    fn test_filter_matches_description() {
        assert_eq!(
            should_include_named_item(
                "Tiana Bartoletta",
                &Some("London 2012".to_string()),
                &Some("london".to_string())
            ),
            true
        );
    }

    #[test]
    fn test_non_matching_filter() {
        assert_eq!(
            should_include_named_item(
                "Allyson Felix",
                &Some("London 2012".to_string()),
                &Some("salt lake city".to_string())
            ),
            false
        );
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::operators::{Exchange, Probe};
use timely::progress::nested::product::Product;
use timely::progress::timestamp::RootTimestamp;

use differential_dataflow::input::Input;
use differential_dataflow::operators::arrange::Arrange;
use differential_dataflow::operators::count::CountTotalCore;

use differential_dataflow::trace::implementations::ord::OrdKeySpine;

#[derive(Debug)]
enum Comp {
    Nothing,
    Exchange,
    Arrange,
    Count,
}

#[derive(Debug)]
enum Mode {
    OpenLoop,
    ClosedLoop,
}

fn main() {

    let keys: usize = std::env::args().nth(1).unwrap().parse().unwrap();
    let recs: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let rate: usize = std::env::args().nth(3).unwrap().parse().unwrap();
    let work: usize = std::env::args().nth(4).unwrap().parse().unwrap();
    let comp: Comp = match std::env::args().nth(5).unwrap().as_str() {
        "exchange" => Comp::Exchange,
        "arrange" => Comp::Arrange,
        "count" => Comp::Count,
        _ => Comp::Nothing,
    };
    let mode: Mode = if std::env::args().any(|x| x == "open-loop") { Mode::OpenLoop } else { Mode::ClosedLoop };

    // define a new computational scope, in which to run BFS
    timely::execute_from_args(std::env::args().skip(4), move |worker| {

        // create a a degree counting differential dataflow
        let (mut input, probe) = worker.dataflow::<u64,_,_>(|scope| {

            let (handle, data) = scope.new_collection();

            let probe = match comp {
                Comp::Nothing => data.probe(),
                Comp::Exchange => data.inner.exchange(|&(x,_,_): &((usize,()),_,_)| x.0 as u64).probe(),
                Comp::Arrange => data.arrange(OrdKeySpine::<usize, Product<RootTimestamp,u64>,isize>::with_effort(work)).stream.probe(),
                Comp::Count => data.arrange(OrdKeySpine::<usize, Product<RootTimestamp,u64>,isize>::with_effort(work)).count_total_core().probe(),
            };

            (handle, probe)
        });

        let index = worker.index();
        let peers = worker.peers();

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for deletions

        let timer = ::std::time::Instant::now();

        for _ in 0 .. ((recs as usize) / peers) + if index < ((recs as usize) % peers) { 1 } else { 0 } {
            input.insert((rng1.gen_range(0, keys),()));
        }

        input.advance_to(1u64);
        input.flush();
        while probe.less_than(input.time()) { worker.step(); }

        if index == 0 {
            let elapsed1 = timer.elapsed();
            let elapsed1_ns = elapsed1.as_secs() * 1_000_000_000 + (elapsed1.subsec_nanos() as u64);
            // println!("{:?}\tdata loaded; rate: {:?}", elapsed1, 1000000000.0 * (recs as f64) / (elapsed1_ns as f64));
            println!("ARRANGE\tLOADING\t{}\t{:?}", peers, 1000000000.0 * (recs as f64) / (elapsed1_ns as f64));
        }

        if rate > 0 {

            let timer = ::std::time::Instant::now();
            // let mut counts = vec![0u64; 64];

            let mut counts = vec![[0u64; 16]; 64];

            match mode {

                // closed-loop latency-throughput test, parameterized by rate size.
                Mode::ClosedLoop => {

                    let mut wave = 1;
                    let mut elapsed = timer.elapsed();

                    while elapsed.as_secs() < 25 {

                        for round in 0 .. rate {
                            input.advance_to((((wave * rate) + round) * peers + index) as u64);
                            input.insert((rng1.gen_range(0, keys),()));
                            input.remove((rng2.gen_range(0, keys),()));
                        }
                        wave += 1;
                        input.advance_to((wave * rate * peers) as u64);
                        input.flush();

                        let elapsed1 = elapsed.clone();
                        let elapsed1_ns = elapsed1.as_secs() * 1_000_000_000 + (elapsed1.subsec_nanos() as u64);
                        while probe.less_than(input.time()) { worker.step(); }
                        elapsed = timer.elapsed();
                        let elapsed2 = elapsed.clone();
                        let elapsed2_ns = elapsed2.as_secs() * 1_000_000_000 + (elapsed2.subsec_nanos() as u64);
                        let count_index = (elapsed2_ns - elapsed1_ns).next_power_of_two().trailing_zeros() as usize;
                        if elapsed.as_secs() > 5 {
                            let low_bits = ((elapsed2_ns - elapsed1_ns) >> (count_index - 5)) & 0xF;
                            counts[count_index][low_bits as usize] += 1;
                        }
                    }

                    let elapsed = timer.elapsed();
                    let seconds = elapsed.as_secs() as f64 + (elapsed.subsec_nanos() as f64) / 1000000000.0;
                    if index == 0 {
                        // println!("{:?}, {:?}", seconds / (wave - 1) as f64, 2.0 * ((wave - 1) * rate * peers) as f64 / seconds);
                        println!("ARRANGE\tTHROUGHPUT\t{}\t{:?}", peers, 2.0 * ((wave - 1) * rate * peers) as f64 / seconds);
                    }

                },
                Mode::OpenLoop => {

                    let requests_per_sec = rate / 2;
                    let ns_per_request = 1_000_000_000 / requests_per_sec;
                    let mut request_counter = peers + index;    // skip first request for each.
                    let mut ack_counter = peers + index;

                    let mut inserted_ns = 1;

                    while ((timer.elapsed().as_secs() as usize) * rate) < (10 * keys) {

                        // Open-loop latency-throughput test, parameterized by offered rate `ns_per_request`.
                        let elapsed = timer.elapsed();
                        let elapsed_ns = elapsed.as_secs() * 1_000_000_000 + (elapsed.subsec_nanos() as u64);

                        // Determine completed ns.
                        let acknowledged_ns: u64 = probe.with_frontier(|frontier| frontier[0].inner);

                        // any un-recorded measurements that are complete should be recorded.
                        while ((ack_counter * ns_per_request) as u64) < acknowledged_ns {
                            let requested_at = (ack_counter * ns_per_request) as u64;
                            let count_index = (elapsed_ns - requested_at).next_power_of_two().trailing_zeros() as usize;
                            if (elapsed.as_secs() as usize) * rate > 5 * keys {
                                // counts[count_index] += 1;
                                let low_bits = ((elapsed_ns - requested_at) >> (count_index - 5)) & 0xF;
                                counts[count_index][low_bits as usize] += 1;
                            }
                            ack_counter += peers;
                        }

                        // Now, should we introduce more records before stepping the worker?
                        //
                        // Thinking: inserted_ns - acknowledged_ns is some amount of time that
                        // is currently outstanding in the system, and we needn't advance our
                        // inputs unless by this order of magnitude.
                        //
                        // The more sophisticated plan is: we compute the next power of two
                        // greater than inserted_ns - acknowledged_ns and look for the last
                        // multiple of this number in the interval [inserted_ns, elapsed_ns].
                        // If such a multiple exists, we introduce records to that point and
                        // advance the input.

                        // let scale = (inserted_ns - acknowledged_ns).next_power_of_two();
                        // let target_ns = elapsed_ns & !(scale - 1);

                        // let target_ns = if acknowledged_ns >= inserted_ns { elapsed_ns } else { inserted_ns };

                        let target_ns = elapsed_ns & !((1 << 20) - 1);

                        if inserted_ns < target_ns {

                            while ((request_counter * ns_per_request) as u64) < target_ns {
                                input.advance_to((request_counter * ns_per_request) as u64);
                                input.insert((rng1.gen_range(0, keys),()));
                                input.remove((rng2.gen_range(0, keys),()));
                                request_counter += peers;
                            }
                            input.advance_to(target_ns);
                            input.flush();
                            inserted_ns = target_ns;
                        }

                        worker.step();
                    }

                }
            }

            if index == 0 {

                let mut results = Vec::new();
                let total = counts.iter().map(|x| x.iter().sum::<u64>()).sum();
                let mut sum = 0;
                for index in (10 .. counts.len()).rev() {
                    for sub in (0 .. 16).rev() {
                        if sum > 0 && sum < total {
                            let latency = (1 << (index-1)) + (sub << (index-5));
                            let fraction = (sum as f64) / (total as f64);
                            results.push((latency, fraction));
                        }
                        sum += counts[index][sub];
                    }
                }
                for (latency, fraction) in results.drain(..).rev() {
                    println!("ARRANGE\tLATENCY\t{}\t{}\t{}\t{}\t{}\t{:?}\t{:?}\t{}\t{}", peers, keys, recs, rate, work, comp, mode, latency, fraction);
                }
            }
        }

    }).unwrap();
}<commit_msg>updated harness<commit_after>extern crate rand;
extern crate timely;
extern crate differential_dataflow;

use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::operators::{Exchange, Probe};
use timely::progress::nested::product::Product;
use timely::progress::timestamp::RootTimestamp;

use differential_dataflow::input::Input;
use differential_dataflow::operators::arrange::Arrange;
use differential_dataflow::operators::count::CountTotalCore;

use differential_dataflow::trace::implementations::ord::OrdKeySpine;

#[derive(Debug)]
enum Comp {
    Nothing,
    Exchange,
    Arrange,
    Count,
}

#[derive(Debug)]
enum Mode {
    OpenLoop,
    ClosedLoop,
}

fn main() {

    let keys: usize = std::env::args().nth(1).unwrap().parse().unwrap();
    let recs: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let rate: usize = std::env::args().nth(3).unwrap().parse().unwrap();
    let work: usize = std::env::args().nth(4).unwrap().parse().unwrap_or(usize::max_value());
    let comp: Comp = match std::env::args().nth(5).unwrap().as_str() {
        "exchange" => Comp::Exchange,
        "arrange" => Comp::Arrange,
        "count" => Comp::Count,
        _ => Comp::Nothing,
    };
    let mode: Mode = if std::env::args().any(|x| x == "open-loop") { Mode::OpenLoop } else { Mode::ClosedLoop };

    // define a new computational scope, in which to run BFS
    timely::execute_from_args(std::env::args().skip(4), move |worker| {

        // create a a degree counting differential dataflow
        let (mut input, probe) = worker.dataflow::<u64,_,_>(|scope| {

            let (handle, data) = scope.new_collection();

            let probe = match comp {
                Comp::Nothing => data.probe(),
                Comp::Exchange => data.inner.exchange(|&(x,_,_): &((usize,()),_,_)| x.0 as u64).probe(),
                Comp::Arrange => data.arrange(OrdKeySpine::<usize, Product<RootTimestamp,u64>,isize>::with_effort(work)).stream.probe(),
                Comp::Count => data.arrange(OrdKeySpine::<usize, Product<RootTimestamp,u64>,isize>::with_effort(work)).count_total_core().probe(),
            };

            (handle, probe)
        });

        let index = worker.index();
        let peers = worker.peers();

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for deletions

        let timer = ::std::time::Instant::now();

        for _ in 0 .. ((recs as usize) / peers) + if index < ((recs as usize) % peers) { 1 } else { 0 } {
            input.insert((rng1.gen_range(0, keys),()));
        }

        input.advance_to(1u64);
        input.flush();
        while probe.less_than(input.time()) { worker.step(); }

        if index == 0 {
            let elapsed1 = timer.elapsed();
            let elapsed1_ns = elapsed1.as_secs() * 1_000_000_000 + (elapsed1.subsec_nanos() as u64);
            // println!("{:?}\tdata loaded; rate: {:?}", elapsed1, 1000000000.0 * (recs as f64) / (elapsed1_ns as f64));
            println!("ARRANGE\tLOADING\t{}\t{:?}", peers, 1000000000.0 * (recs as f64) / (elapsed1_ns as f64));
        }

        if rate > 0 {

            let timer = ::std::time::Instant::now();
            // let mut counts = vec![0u64; 64];

            let mut counts = vec![[0u64; 16]; 64];

            match mode {

                // closed-loop latency-throughput test, parameterized by rate size.
                Mode::ClosedLoop => {

                    let mut wave = 1;
                    let mut elapsed = timer.elapsed();

                    while elapsed.as_secs() < 25 {

                        for round in 0 .. rate {
                            input.advance_to((((wave * rate) + round) * peers + index) as u64);
                            input.insert((rng1.gen_range(0, keys),()));
                            input.remove((rng2.gen_range(0, keys),()));
                        }
                        wave += 1;
                        input.advance_to((wave * rate * peers) as u64);
                        input.flush();

                        let elapsed1 = elapsed.clone();
                        let elapsed1_ns = elapsed1.as_secs() * 1_000_000_000 + (elapsed1.subsec_nanos() as u64);
                        while probe.less_than(input.time()) { worker.step(); }
                        elapsed = timer.elapsed();
                        let elapsed2 = elapsed.clone();
                        let elapsed2_ns = elapsed2.as_secs() * 1_000_000_000 + (elapsed2.subsec_nanos() as u64);
                        let count_index = (elapsed2_ns - elapsed1_ns).next_power_of_two().trailing_zeros() as usize;
                        if elapsed.as_secs() > 5 {
                            let low_bits = ((elapsed2_ns - elapsed1_ns) >> (count_index - 5)) & 0xF;
                            counts[count_index][low_bits as usize] += 1;
                        }
                    }

                    let elapsed = timer.elapsed();
                    let seconds = elapsed.as_secs() as f64 + (elapsed.subsec_nanos() as f64) / 1000000000.0;
                    if index == 0 {
                        // println!("{:?}, {:?}", seconds / (wave - 1) as f64, 2.0 * ((wave - 1) * rate * peers) as f64 / seconds);
                        println!("ARRANGE\tTHROUGHPUT\t{}\t{:?}", peers, 2.0 * ((wave - 1) * rate * peers) as f64 / seconds);
                    }

                },
                Mode::OpenLoop => {

                    let requests_per_sec = rate / 2;
                    let ns_per_request = 1_000_000_000 / requests_per_sec;
                    let mut request_counter = peers + index;    // skip first request for each.
                    let mut ack_counter = peers + index;

                    let mut inserted_ns = 1;

                    let ack_target = 10 * keys;
                    while ack_counter < ack_target {
                    // while ((timer.elapsed().as_secs() as usize) * rate) < (10 * keys) {

                        // Open-loop latency-throughput test, parameterized by offered rate `ns_per_request`.
                        let elapsed = timer.elapsed();
                        let elapsed_ns = elapsed.as_secs() * 1_000_000_000 + (elapsed.subsec_nanos() as u64);

                        // Determine completed ns.
                        let acknowledged_ns: u64 = probe.with_frontier(|frontier| frontier[0].inner);

                        // any un-recorded measurements that are complete should be recorded.
                        while ((ack_counter * ns_per_request) as u64) < acknowledged_ns && ack_counter < ack_target {
                            let requested_at = (ack_counter * ns_per_request) as u64;
                            let count_index = (elapsed_ns - requested_at).next_power_of_two().trailing_zeros() as usize;
                            if (elapsed.as_secs() as usize) * rate > 5 * keys {
                                // counts[count_index] += 1;
                                let low_bits = ((elapsed_ns - requested_at) >> (count_index - 5)) & 0xF;
                                counts[count_index][low_bits as usize] += 1;
                            }
                            ack_counter += peers;
                        }

                        // Now, should we introduce more records before stepping the worker?
                        //
                        // Thinking: inserted_ns - acknowledged_ns is some amount of time that
                        // is currently outstanding in the system, and we needn't advance our
                        // inputs unless by this order of magnitude.
                        //
                        // The more sophisticated plan is: we compute the next power of two
                        // greater than inserted_ns - acknowledged_ns and look for the last
                        // multiple of this number in the interval [inserted_ns, elapsed_ns].
                        // If such a multiple exists, we introduce records to that point and
                        // advance the input.

                        // let scale = (inserted_ns - acknowledged_ns).next_power_of_two();
                        // let target_ns = elapsed_ns & !(scale - 1);

                        // let target_ns = if acknowledged_ns >= inserted_ns { elapsed_ns } else { inserted_ns };

                        let target_ns = elapsed_ns & !((1 << 20) - 1);

                        if inserted_ns < target_ns {

                            while ((request_counter * ns_per_request) as u64) < target_ns {
                                input.advance_to((request_counter * ns_per_request) as u64);
                                input.insert((rng1.gen_range(0, keys),()));
                                input.remove((rng2.gen_range(0, keys),()));
                                request_counter += peers;
                            }
                            input.advance_to(target_ns);
                            input.flush();
                            inserted_ns = target_ns;
                        }

                        worker.step();
                    }

                }
            }

            if index == 0 {

                let mut results = Vec::new();
                let total = counts.iter().map(|x| x.iter().sum::<u64>()).sum();
                let mut sum = 0;
                for index in (10 .. counts.len()).rev() {
                    for sub in (0 .. 16).rev() {
                        if sum > 0 && sum < total {
                            let latency = (1 << (index-1)) + (sub << (index-5));
                            let fraction = (sum as f64) / (total as f64);
                            results.push((latency, fraction));
                        }
                        sum += counts[index][sub];
                    }
                }
                for (latency, fraction) in results.drain(..).rev() {
                    println!("ARRANGE\tLATENCY\t{}\t{}\t{}\t{}\t{}\t{:?}\t{:?}\t{}\t{}", peers, keys, recs, rate, work, comp, mode, latency, fraction);
                }
            }
        }

    }).unwrap();
}<|endoftext|>