<commit_before>extern crate sfunc;

use std::rand::Rng;
use std::rand::distributions::{Normal, IndependentSample};

use super::Distribution;

/// A Gaussian distribution.
pub struct Gaussian {
    /// The mean value.
    pub mu: f64,
    /// The standard deviation.
    pub sigma: f64,

    normal: Normal,
}

impl Gaussian {
    /// Creates a Gaussian distribution with the mean value `mu` and standard
    /// deviation `sigma`.
    #[inline]
    pub fn new(mu: f64, sigma: f64) -> Gaussian {
        Gaussian {
            mu: mu,
            sigma: sigma,
            normal: Normal::new(0.0, 1.0),
        }
    }
}

impl Distribution<f64> for Gaussian {
    fn cdf(&self, x: f64) -> f64 {
        use self::sfunc::erf;
        (1.0 + erf((x - self.mu) / (self.sigma * Float::sqrt2()))) / 2.0
    }

    /// Compute the inverse of the cummulative distribution function at
    /// probability `p`.
    ///
    /// The code is based on a [C implementation][1] by John Burkardt.
    ///
    /// [1]: http://people.sc.fsu.edu/~jburkardt/c_src/asa241/asa241.html
    fn inv_cdf(&self, p: f64) -> f64 {
        use self::sfunc::{log, sqrt};

        const CONST1: f64 = 0.180625;
        const CONST2: f64 = 1.6;
        const SPLIT1: f64 = 0.425;
        const SPLIT2: f64 = 5.0;

        const A: [f64, ..8] = [
            3.3871328727963666080,
            1.3314166789178437745e+2,
            1.9715909503065514427e+3,
            1.3731693765509461125e+4,
            4.5921953931549871457e+4,
            6.7265770927008700853e+4,
            3.3430575583588128105e+4,
            2.5090809287301226727e+3,
        ];
        const B: [f64, ..8] = [
            1.0,
            4.2313330701600911252e+1,
            6.8718700749205790830e+2,
            5.3941960214247511077e+3,
            2.1213794301586595867e+4,
            3.9307895800092710610e+4,
            2.8729085735721942674e+4,
            5.2264952788528545610e+3,
        ];
        const C: [f64, ..8] = [
            1.42343711074968357734,
            4.63033784615654529590,
            5.76949722146069140550,
            3.64784832476320460504,
            1.27045825245236838258,
            2.41780725177450611770e-1,
            2.27238449892691845833e-2,
            7.74545014278341407640e-4,
        ];
        const D: [f64, ..8] = [
            1.0,
            2.05319162663775882187,
            1.67638483018380384940,
            6.89767334985100004550e-1,
            1.48103976427480074590e-1,
            1.51986665636164571966e-2,
            5.47593808499534494600e-4,
            1.05075007164441684324e-9,
        ];
        const E: [f64, ..8] = [
            6.65790464350110377720,
            5.46378491116411436990,
            1.78482653991729133580,
            2.96560571828504891230e-1,
            2.65321895265761230930e-2,
            1.24266094738807843860e-3,
            2.71155556874348757815e-5,
            2.01033439929228813265e-7,
        ];
        const F: [f64, ..8] = [
            1.0,
            5.99832206555887937690e-1,
            1.36929880922735805310e-1,
            1.48753612908506148525e-2,
            7.86869131145613259100e-4,
            1.84631831751005468180e-5,
            1.42151175831644588870e-7,
            2.04426310338993978564e-15,
        ];

        #[inline]
        fn poly(c: &[f64], x: f64) -> f64 {
            c.iter().rev().fold(0.0, |y, &c| y * x + c)
        }

        if p <= 0.0 {
            return Float::neg_infinity();
        }
        if 1.0 <= p {
            return Float::infinity();
        }

        let q = p - 0.5;

        if ::std::num::abs(q) <= SPLIT1 {
            let x = CONST1 - q * q;
            return self.mu + self.sigma * q * poly(&A, x) / poly(&B, x);
        }

        let mut x = if q < 0.0 { p } else { 1.0 - p };

        x = sqrt(-log(x));

        if x <= SPLIT2 {
            x -= CONST2;
            x = poly(&C, x) / poly(&D, x);
        } else {
            x -= SPLIT2;
            x = poly(&E, x) / poly(&F, x);
        }

        if q < 0.0 {
            x = -x;
        }

        self.mu + self.sigma * x
    }

    #[inline]
    fn sample<R: Rng>(&self, rng: &mut R) -> f64 {
        self.normal.ind_sample(rng)
    }
}

#[cfg(test)]
mod test {
    use super::super::Distribution;
    use super::Gaussian;

    macro_rules! assert_almost_eq(
        ($x:expr, $y:expr) => ({
            let e: f64 = ::std::f64::EPSILON.sqrt();
            let x: Vec<f64> = $x;
            let y: Vec<f64> = $y;
            for i in range(0u, x.len()) {
                if x[i].is_finite() {
                    assert!(::std::num::abs(x[i] - y[i]) < e,
                            "expected {:e} ~ {:e}", x[i], y[i]);
                } else {
                    assert_eq!(x[i], y[i]);
                }
            }
        });
    )

    #[test]
    fn cdf() {
        let gaussian = Gaussian::new(1.0, 2.0);

        let x = vec![-4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5,
                     1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0];
        let p = vec![6.209665325776139e-03, 1.222447265504470e-02,
                     2.275013194817922e-02, 4.005915686381709e-02,
                     6.680720126885809e-02, 1.056497736668553e-01,
                     1.586552539314571e-01, 2.266273523768682e-01,
                     3.085375387259869e-01, 4.012936743170763e-01,
                     5.000000000000000e-01, 5.987063256829237e-01,
                     6.914624612740131e-01, 7.733726476231317e-01,
                     8.413447460685429e-01, 8.943502263331446e-01,
                     9.331927987311419e-01];

        assert_almost_eq!(x.iter().map(|&x| {
            gaussian.cdf(x)
        }).collect(), p);
    }

    #[test]
    fn inv_cdf() {
        let gaussian = Gaussian::new(-1.0, 0.25);

        let p = vec![0.00, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40,
                     0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85,
                     0.90, 0.95, 1.00];
        let x = vec![Float::neg_infinity(), -1.411213406737868e+00,
                     -1.320387891386150e+00, -1.259108347373447e+00,
                     -1.210405308393228e+00, -1.168622437549020e+00,
                     -1.131100128177010e+00, -1.096330116601892e+00,
                     -1.063336775783950e+00, -1.031415336713768e+00,
                     -1.000000000000000e+00, -9.685846632862315e-01,
                     -9.366632242160501e-01, -9.036698833981082e-01,
                     -8.688998718229899e-01, -8.313775624509796e-01,
                     -7.895946916067714e-01, -7.408916526265525e-01,
                     -6.796121086138498e-01, -5.887865932621319e-01,
                     Float::infinity()];

        assert_almost_eq!(p.iter().map(|&p| {
            gaussian.inv_cdf(p)
        }).collect(), x);
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use super::super::Distribution;
    use super::Gaussian;

    #[bench]
    fn sample(bench: &mut test::Bencher) {
        let mut rng = ::std::rand::task_rng();
        let gaussian = Gaussian::new(0.0, 1.0);
        bench.iter(|| {
            test::black_box(gaussian.sample(&mut rng))
        });
    }
}
<commit_msg>Useless alignment in tests<commit_after>extern crate sfunc;

use std::rand::Rng;
use std::rand::distributions::{Normal, IndependentSample};

use super::Distribution;

/// A Gaussian distribution.
pub struct Gaussian {
    /// The mean value.
    pub mu: f64,
    /// The standard deviation.
    pub sigma: f64,

    normal: Normal,
}

impl Gaussian {
    /// Creates a Gaussian distribution with the mean value `mu` and standard
    /// deviation `sigma`.
    #[inline]
    pub fn new(mu: f64, sigma: f64) -> Gaussian {
        Gaussian {
            mu: mu,
            sigma: sigma,
            normal: Normal::new(0.0, 1.0),
        }
    }
}

impl Distribution<f64> for Gaussian {
    fn cdf(&self, x: f64) -> f64 {
        use self::sfunc::erf;
        (1.0 + erf((x - self.mu) / (self.sigma * Float::sqrt2()))) / 2.0
    }

    /// Compute the inverse of the cummulative distribution function at
    /// probability `p`.
    ///
    /// The code is based on a [C implementation][1] by John Burkardt.
    ///
    /// [1]: http://people.sc.fsu.edu/~jburkardt/c_src/asa241/asa241.html
    fn inv_cdf(&self, p: f64) -> f64 {
        use self::sfunc::{log, sqrt};

        const CONST1: f64 = 0.180625;
        const CONST2: f64 = 1.6;
        const SPLIT1: f64 = 0.425;
        const SPLIT2: f64 = 5.0;
        const A: [f64, ..8] = [3.3871328727963666080,
                               1.3314166789178437745e+2,
                               1.9715909503065514427e+3,
                               1.3731693765509461125e+4,
                               4.5921953931549871457e+4,
                               6.7265770927008700853e+4,
                               3.3430575583588128105e+4,
                               2.5090809287301226727e+3];
        const B: [f64, ..8] = [1.0000000000000000000,
                               4.2313330701600911252e+1,
                               6.8718700749205790830e+2,
                               5.3941960214247511077e+3,
                               2.1213794301586595867e+4,
                               3.9307895800092710610e+4,
                               2.8729085735721942674e+4,
                               5.2264952788528545610e+3];
        const C: [f64, ..8] = [1.42343711074968357734,
                               4.63033784615654529590,
                               5.76949722146069140550,
                               3.64784832476320460504,
                               1.27045825245236838258,
                               2.41780725177450611770e-1,
                               2.27238449892691845833e-2,
                               7.74545014278341407640e-4];
        const D: [f64, ..8] = [1.00000000000000000000,
                               2.05319162663775882187,
                               1.67638483018380384940,
                               6.89767334985100004550e-1,
                               1.48103976427480074590e-1,
                               1.51986665636164571966e-2,
                               5.47593808499534494600e-4,
                               1.05075007164441684324e-9];
        const E: [f64, ..8] = [6.65790464350110377720,
                               5.46378491116411436990,
                               1.78482653991729133580,
                               2.96560571828504891230e-1,
                               2.65321895265761230930e-2,
                               1.24266094738807843860e-3,
                               2.71155556874348757815e-5,
                               2.01033439929228813265e-7];
        const F: [f64, ..8] = [1.00000000000000000000,
                               5.99832206555887937690e-1,
                               1.36929880922735805310e-1,
                               1.48753612908506148525e-2,
                               7.86869131145613259100e-4,
                               1.84631831751005468180e-5,
                               1.42151175831644588870e-7,
                               2.04426310338993978564e-15];

        #[inline]
        fn poly(c: &[f64], x: f64) -> f64 {
            c.iter().rev().fold(0.0, |y, &c| y * x + c)
        }

        if p <= 0.0 {
            return Float::neg_infinity();
        }
        if 1.0 <= p {
            return Float::infinity();
        }

        let q = p - 0.5;

        if ::std::num::abs(q) <= SPLIT1 {
            let x = CONST1 - q * q;
            return self.mu + self.sigma * q * poly(&A, x) / poly(&B, x);
        }

        let mut x = if q < 0.0 { p } else { 1.0 - p };

        x = sqrt(-log(x));

        if x <= SPLIT2 {
            x -= CONST2;
            x = poly(&C, x) / poly(&D, x);
        } else {
            x -= SPLIT2;
            x = poly(&E, x) / poly(&F, x);
        }

        if q < 0.0 {
            x = -x;
        }

        self.mu + self.sigma * x
    }

    #[inline]
    fn sample<R: Rng>(&self, rng: &mut R) -> f64 {
        self.normal.ind_sample(rng)
    }
}

#[cfg(test)]
mod test {
    use super::super::Distribution;
    use super::Gaussian;

    macro_rules! assert_almost_eq(
        ($x:expr, $y:expr) => ({
            let e: f64 = ::std::f64::EPSILON.sqrt();
            let x: Vec<f64> = $x;
            let y: Vec<f64> = $y;
            for i in range(0u, x.len()) {
                if x[i].is_finite() {
                    assert!(::std::num::abs(x[i] - y[i]) < e,
                            "expected {:e} ~ {:e}", x[i], y[i]);
                } else {
                    assert_eq!(x[i], y[i]);
                }
            }
        });
    )

    #[test]
    fn cdf() {
        let gaussian = Gaussian::new(1.0, 2.0);

        let x = vec![-4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5,
                     1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0];
        let p = vec![6.209665325776139e-03, 1.222447265504470e-02,
                     2.275013194817922e-02, 4.005915686381709e-02,
                     6.680720126885809e-02, 1.056497736668553e-01,
                     1.586552539314571e-01, 2.266273523768682e-01,
                     3.085375387259869e-01, 4.012936743170763e-01,
                     5.000000000000000e-01, 5.987063256829237e-01,
                     6.914624612740131e-01, 7.733726476231317e-01,
                     8.413447460685429e-01, 8.943502263331446e-01,
                     9.331927987311419e-01];

        assert_almost_eq!(x.iter().map(|&x| {
            gaussian.cdf(x)
        }).collect(), p);
    }

    #[test]
    fn inv_cdf() {
        let gaussian = Gaussian::new(-1.0, 0.25);

        let p = vec![0.00, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40,
                     0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85,
                     0.90, 0.95, 1.00];
        let x = vec![Float::neg_infinity(), -1.411213406737868e+00,
                     -1.320387891386150e+00, -1.259108347373447e+00,
                     -1.210405308393228e+00, -1.168622437549020e+00,
                     -1.131100128177010e+00, -1.096330116601892e+00,
                     -1.063336775783950e+00, -1.031415336713768e+00,
                     -1.000000000000000e+00, -9.685846632862315e-01,
                     -9.366632242160501e-01, -9.036698833981082e-01,
                     -8.688998718229899e-01, -8.313775624509796e-01,
                     -7.895946916067714e-01, -7.408916526265525e-01,
                     -6.796121086138498e-01, -5.887865932621319e-01,
                     Float::infinity()];

        assert_almost_eq!(p.iter().map(|&p| {
            gaussian.inv_cdf(p)
        }).collect(), x);
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use super::super::Distribution;
    use super::Gaussian;

    #[bench]
    fn sample(bench: &mut test::Bencher) {
        let mut rng = ::std::rand::task_rng();
        let gaussian = Gaussian::new(0.0, 1.0);
        bench.iter(|| {
            test::black_box(gaussian.sample(&mut rng))
        });
    }
}
<|endoftext|>


<commit_before>use crate::stable_hasher::{HashStable, StableHasher};
use crate::sync::{MappedReadGuard, ReadGuard, RwLock};

/// The `Steal` struct is intended to used as the value for a query.
/// Specifically, we sometimes have queries (*cough* MIR *cough*)
/// where we create a large, complex value that we want to iteratively
/// update (e.g., optimize). We could clone the value for each
/// optimization, but that'd be expensive. And yet we don't just want
/// to mutate it in place, because that would spoil the idea that
/// queries are these pure functions that produce an immutable value
/// (since if you did the query twice, you could observe the mutations).
/// So instead we have the query produce a `&'tcx Steal<mir::Body<'tcx>>`
/// (to be very specific). Now we can read from this
/// as much as we want (using `borrow()`), but you can also
/// `steal()`. Once you steal, any further attempt to read will panic.
/// Therefore, we know that -- assuming no ICE -- nobody is observing
/// the fact that the MIR was updated.
///
/// Obviously, whenever you have a query that yields a `Steal` value,
/// you must treat it with caution, and make sure that you know that
/// -- once the value is stolen -- it will never be read from again.
//
// FIXME(#41710): what is the best way to model linear queries?
pub struct Steal<T> {
    value: RwLock<Option<T>>,
}

impl<T> Steal<T> {
    pub fn new(value: T) -> Self {
        Steal { value: RwLock::new(Some(value)) }
    }

    pub fn borrow(&self) -> MappedReadGuard<'_, T> {
        ReadGuard::map(self.value.borrow(), |opt| match *opt {
            None => panic!("attempted to read from stolen value"),
            Some(ref v) => v,
        })
    }

    pub fn steal(&self) -> T {
        let value_ref = &mut *self.value.try_write().expect("stealing value which is locked");
        let value = value_ref.take();
        value.expect("attempt to read from stolen value")
    }
}

impl<CTX, T: HashStable<CTX>> HashStable<CTX> for Steal<T> {
    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
        self.borrow().hash_stable(hcx, hasher);
    }
}
<commit_msg>Rollup merge of #81125 - jyn514:track-caller, r=lcnr<commit_after>use crate::stable_hasher::{HashStable, StableHasher};
use crate::sync::{MappedReadGuard, ReadGuard, RwLock};

/// The `Steal` struct is intended to used as the value for a query.
/// Specifically, we sometimes have queries (*cough* MIR *cough*)
/// where we create a large, complex value that we want to iteratively
/// update (e.g., optimize). We could clone the value for each
/// optimization, but that'd be expensive. And yet we don't just want
/// to mutate it in place, because that would spoil the idea that
/// queries are these pure functions that produce an immutable value
/// (since if you did the query twice, you could observe the mutations).
/// So instead we have the query produce a `&'tcx Steal<mir::Body<'tcx>>`
/// (to be very specific). Now we can read from this
/// as much as we want (using `borrow()`), but you can also
/// `steal()`. Once you steal, any further attempt to read will panic.
/// Therefore, we know that -- assuming no ICE -- nobody is observing
/// the fact that the MIR was updated.
///
/// Obviously, whenever you have a query that yields a `Steal` value,
/// you must treat it with caution, and make sure that you know that
/// -- once the value is stolen -- it will never be read from again.
//
// FIXME(#41710): what is the best way to model linear queries?
pub struct Steal<T> {
    value: RwLock<Option<T>>,
}

impl<T> Steal<T> {
    pub fn new(value: T) -> Self {
        Steal { value: RwLock::new(Some(value)) }
    }

    #[track_caller]
    pub fn borrow(&self) -> MappedReadGuard<'_, T> {
        ReadGuard::map(self.value.borrow(), |opt| match *opt {
            None => panic!("attempted to read from stolen value"),
            Some(ref v) => v,
        })
    }

    #[track_caller]
    pub fn steal(&self) -> T {
        let value_ref = &mut *self.value.try_write().expect("stealing value which is locked");
        let value = value_ref.take();
        value.expect("attempt to steal from stolen value")
    }
}

impl<CTX, T: HashStable<CTX>> HashStable<CTX> for Steal<T> {
    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
        self.borrow().hash_stable(hcx, hasher);
    }
}
<|endoftext|>


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

//! Factory extension. Provides resource construction shortcuts.

use device;
use device::{handle, tex};
use device::shade::{Stage, CreateShaderError};
use render::mesh::{Mesh, VertexFormat};
use super::shade::*;

/// Factory extension trait
pub trait FactoryExt<R: device::Resources> {
    /// Create a new mesh from the given vertex data.
    /// Convenience function around `create_buffer` and `Mesh::from_format`.
    fn create_mesh<T: VertexFormat + Copy>(&mut self, data: &[T]) -> Mesh<R>;
    /// Create a simple program given a vertex shader with a fragment one.
    fn link_program(&mut self, vs_code: &[u8], fs_code: &[u8])
                    -> Result<handle::Program<R>, ProgramError>;
    /// Create a simple program given `ShaderSource` versions of vertex and
    /// fragment shaders, chooss the matching versions for the device.
    fn link_program_source(&mut self, vs_src: ShaderSource, fs_src: ShaderSource,
                           caps: &device::Capabilities)
                           -> Result<handle::Program<R>, ProgramError>;
    /// Create a simple RGBA8 2D texture.
    fn create_texture_rgba8(&mut self, width: u16, height: u16)
                            -> Result<handle::Texture<R>, tex::TextureError>;
    /// Create RGBA8 2D texture with given contents and mipmap chain.
    fn create_texture_rgba8_static(&mut self, width: u16, height: u16, data: &[u32])
                                   -> Result<handle::Texture<R>, tex::TextureError>;
    /// Create a simple depth+stencil 2D texture.
    fn create_texture_depth_stencil(&mut self, width: u16, height: u16)
                                    -> Result<handle::Texture<R>, tex::TextureError>;
}

impl<R: device::Resources, F: device::Factory<R>> FactoryExt<R> for F {
    fn create_mesh<T: VertexFormat + Copy>(&mut self, data: &[T]) -> Mesh<R> {
        let nv = data.len();
        //debug_assert!(nv < self.max_vertex_count); //TODO
        let buf = self.create_buffer_static(data);
        Mesh::from_format(buf, nv as device::VertexCount)
    }

    fn link_program(&mut self, vs_code: &[u8], fs_code: &[u8])
                    -> Result<handle::Program<R>, ProgramError> {
        let vs = match self.create_shader(Stage::Vertex, vs_code) {
            Ok(s) => s,
            Err(e) => return Err(ProgramError::Vertex(e)),
        };
        let fs = match self.create_shader(Stage::Fragment, fs_code) {
            Ok(s) => s,
            Err(e) => return Err(ProgramError::Fragment(e)),
        };

        self.create_program(&[vs, fs], None)
            .map_err(|e| ProgramError::Link(e))
    }

    fn link_program_source(&mut self, vs_src: ShaderSource, fs_src: ShaderSource,
                           caps: &device::Capabilities)
                           -> Result<handle::Program<R>, ProgramError> {
        let model = caps.shader_model;
        let err_model = CreateShaderError::ModelNotSupported;

        let vs = match vs_src.choose(model) {
            Ok(code) => match self.create_shader(Stage::Vertex, code) {
                Ok(s) => s,
                Err(e) => return Err(ProgramError::Vertex(e)),
            },
            Err(_) => return Err(ProgramError::Vertex(err_model))
        };

        let fs = match fs_src.choose(model) {
            Ok(code) => match self.create_shader(Stage::Fragment, code) {
                Ok(s) => s,
                Err(e) => return Err(ProgramError::Fragment(e)),
            },
            Err(_) => return Err(ProgramError::Fragment(err_model))
        };

        self.create_program(&[vs, fs], Some(fs_src.targets))
            .map_err(|e| ProgramError::Link(e))
    }

    fn create_texture_rgba8(&mut self, width: u16, height: u16)
                            -> Result<handle::Texture<R>, tex::TextureError> {
        self.create_texture(tex::TextureInfo {
            width: width,
            height: height,
            depth: 1,
            levels: 1,
            kind: tex::TextureKind::Texture2D,
            format: tex::RGBA8,
        })
    }

    fn create_texture_rgba8_static(&mut self, width: u16, height: u16, data: &[u32])
                                   -> Result<handle::Texture<R>, tex::TextureError> {
        let info = tex::TextureInfo {
            width: width,
            height: height,
            depth: 1,
            levels: 99,
            kind: tex::TextureKind::Texture2D,
            format: tex::RGBA8,
        };
        match self.create_texture_static(info, data) {
            Ok(handle) => {
                self.generate_mipmap(&handle);
                Ok(handle)
            },
            Err(e) => Err(e),
        }
    }

    fn create_texture_depth_stencil(&mut self, width: u16, height: u16)
                                    -> Result<handle::Texture<R>, tex::TextureError> {
        self.create_texture(tex::TextureInfo {
            width: width,
            height: height,
            depth: 0,
            levels: 1,
            kind: tex::TextureKind::Texture2D,
            format: tex::Format::DEPTH24_STENCIL8,
        })
    }
}
<commit_msg>Refactored FactoryExt<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Factory extension. Provides resource construction shortcuts.

use device;
use device::{handle, tex};
use device::shade::{Stage, CreateShaderError};
use render::mesh::{Mesh, VertexFormat};
use super::shade::*;

/// Factory extension trait
pub trait FactoryExt<R: device::Resources>: device::Factory<R> {
    /// Create a new mesh from the given vertex data.
    /// Convenience function around `create_buffer` and `Mesh::from_format`.
    fn create_mesh<T: VertexFormat + Copy>(&mut self, data: &[T]) -> Mesh<R> {
        let nv = data.len();
        //debug_assert!(nv < self.max_vertex_count); //TODO
        let buf = self.create_buffer_static(data);
        Mesh::from_format(buf, nv as device::VertexCount)
    }

    /// Create a simple program given a vertex shader with a fragment one.
    fn link_program(&mut self, vs_code: &[u8], fs_code: &[u8])
                    -> Result<handle::Program<R>, ProgramError> {
        let vs = match self.create_shader(Stage::Vertex, vs_code) {
            Ok(s) => s,
            Err(e) => return Err(ProgramError::Vertex(e)),
        };
        let fs = match self.create_shader(Stage::Fragment, fs_code) {
            Ok(s) => s,
            Err(e) => return Err(ProgramError::Fragment(e)),
        };

        self.create_program(&[vs, fs], None)
            .map_err(|e| ProgramError::Link(e))
    }

    /// Create a simple program given `ShaderSource` versions of vertex and
    /// fragment shaders, chooss the matching versions for the device.
    fn link_program_source(&mut self, vs_src: ShaderSource, fs_src: ShaderSource,
                           caps: &device::Capabilities)
                           -> Result<handle::Program<R>, ProgramError> {
        let model = caps.shader_model;
        let err_model = CreateShaderError::ModelNotSupported;

        let vs = match vs_src.choose(model) {
            Ok(code) => match self.create_shader(Stage::Vertex, code) {
                Ok(s) => s,
                Err(e) => return Err(ProgramError::Vertex(e)),
            },
            Err(_) => return Err(ProgramError::Vertex(err_model))
        };

        let fs = match fs_src.choose(model) {
            Ok(code) => match self.create_shader(Stage::Fragment, code) {
                Ok(s) => s,
                Err(e) => return Err(ProgramError::Fragment(e)),
            },
            Err(_) => return Err(ProgramError::Fragment(err_model))
        };

        self.create_program(&[vs, fs], Some(fs_src.targets))
            .map_err(|e| ProgramError::Link(e))
    }

    /// Create a simple RGBA8 2D texture.
    fn create_texture_rgba8(&mut self, width: u16, height: u16)
                            -> Result<handle::Texture<R>, tex::TextureError> {
        self.create_texture(tex::TextureInfo {
            width: width,
            height: height,
            depth: 1,
            levels: 1,
            kind: tex::TextureKind::Texture2D,
            format: tex::RGBA8,
        })
    }

    /// Create RGBA8 2D texture with given contents and mipmap chain.
    fn create_texture_rgba8_static(&mut self, width: u16, height: u16, data: &[u32])
                                   -> Result<handle::Texture<R>, tex::TextureError> {
        let info = tex::TextureInfo {
            width: width,
            height: height,
            depth: 1,
            levels: 99,
            kind: tex::TextureKind::Texture2D,
            format: tex::RGBA8,
        };
        match self.create_texture_static(info, data) {
            Ok(handle) => {
                self.generate_mipmap(&handle);
                Ok(handle)
            },
            Err(e) => Err(e),
        }
    }

    /// Create a simple depth+stencil 2D texture.
    fn create_texture_depth_stencil(&mut self, width: u16, height: u16)
                                    -> Result<handle::Texture<R>, tex::TextureError> {
        self.create_texture(tex::TextureInfo {
            width: width,
            height: height,
            depth: 0,
            levels: 1,
            kind: tex::TextureKind::Texture2D,
            format: tex::Format::DEPTH24_STENCIL8,
        })
    }
}

impl<R: device::Resources, F: device::Factory<R>> FactoryExt<R> for F {}
<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;

extern crate num;
extern crate byteorder;
extern crate libc;
extern crate argparse;

use test::Bencher;
use std::env;
use std::fs::File;
use std::io::{Read, Write};
use std::io::Cursor;
use std::mem;
use std::iter::FromIterator;
use byteorder::{ByteOrder, LittleEndian, BigEndian, NativeEndian};
use std::time::Duration;
use argparse::{ArgumentParser, StoreTrue, Store};
use std::process::exit;

use libc::{c_int, size_t};
use std::vec;

type c32 = num::Complex<f32>;

macro_rules! timer_start {
    () => {
        {
            let timer = std::time::Instant::now();
            timer
        }
    }
}

macro_rules! timer_stop {
    ($timer:expr, $name:expr) => {
        let d = ($timer).elapsed();
        println!("elapsed time for {}: {:.7}s.", $name, d.as_secs() as f64 + d.subsec_nanos() as f64 / 1.0e9f64);
    }
}

fn kernel1(ai: &mut Vec<f32>, ef: &Vec<c32>) {
    let size = ai.len();
    for i in 0..size {
        ai[i] += ef[i].re.powi(2) + ef[i].im.powi(2);
    }
}

fn kernel2(ai: &mut Vec<f32>, ef_re: &Vec<f32>, ef_im: &Vec<f32>) {
    let size = ai.len();
    for i in 0..size {
        ai[i] += ef_re[i].powi(2) + ef_im[i].powi(2);
    }
}

fn kernel3(ai: &mut Vec<f32>, ef: &Vec<f32>) {
    let size = ai.len();
    for i in 0..size {
        ai[i] += ef[2*i].powi(2) + ef[2*i+1].powi(2);
    }
}

// now play with kernels written in C/C++
#[link(name = "ckernels")]
extern "C" {
    fn kernel4(L: c_int, ai: *mut f32, ef: *const f32);
    fn kernel5(L: c_int, ai: *mut f32, ef: *const f32);
    fn kernel6(L: c_int, ai: *mut f32, ef: *const f32);
    fn kernel7(L: c_int, ai: *mut f32, ef: *const f32);
}

fn kernel8(ai: &Vec<f32>, ef: &Vec<c32>) -> Vec<f32> {
    let x: Vec<f32> = ai.iter()
                .zip( ef.iter() )
                .map(
                    |(x, y)| x + y.re.powi(2) + y.im.powi(2)
                    ).collect();
    x
}

fn kernel9(ai: &mut Vec<f32>, ef: &Vec<c32>) {
    for (x, y) in ai.iter_mut().zip(ef) {
        *x += (*y).re.powi(2) + (*y).im.powi(2);
    }
}

struct Options {
    verbose: bool,
    name: String,
    rep_count: usize,
    kernel_num: isize,
}

fn cook_input_data(parse_options: bool) -> (Options, Vec<f32>, Vec<c32>) {
    let mut options = Options {
        verbose:   false,
        //name:      "./data/add_sum_sq/sum_ef_20077.bin".to_string(),
        name:      "./data/add_sum_sq/sum_ef_20085.bin".to_string(),
        rep_count: 10000,
        kernel_num: -1,
    };

    if parse_options {
        let mut ap = ArgumentParser::new();
        ap.set_description("Time elapsing for add_sum_sq kernels.");
        ap.refer(&mut options.verbose)
            .add_option(&["-v", "--verbose"], StoreTrue,
            "set verbose");
        ap.refer(&mut options.name)
            .add_option(&["-i", "--input"], Store,
            "set name of input file");
        ap.refer(&mut options.rep_count)
            .add_option(&["-n", "--num_iters"], Store,
            "set number of iterations");
        ap.refer(&mut options.kernel_num)
            .add_option(&["-k", "--num_kernel"], Store,
            "set number of kernel");
        match ap.parse_args() {
            Ok(()) => {}
            Err(x) => {
                exit(x);
            }
        }
    }

    if options.verbose {
        println!("input file name : {} number of iterations : {} kernel number : {}",
                 options.name, options.rep_count, options.kernel_num);
    }

    let mut file = File::open(&options.name).ok().expect(&format!("The file {:?} does not exist", &options.name));
    let file_info = file.metadata().ok().expect("Cannot get file metadata");
    if !file_info.is_file() {
        panic!("{:?} is not a file", &options.name);
    }

    if parse_options {
        println!("the file {:?} has length {} bytes", &options.name, file_info.len());
    }

    let mut buf = [0u8; 4];
    file.read(&mut buf[..]);
    let L = LittleEndian::read_u32(&buf[..]);

    if parse_options {
        println!("L : {}", L);
    }

    let size = L as usize;
    let mut grid_buf = Vec::new();
    let sz = file.read_to_end(&mut grid_buf).unwrap();
    let ai = Vec::from_iter((0..size).map(|i| {
                let start = i * mem::size_of::<f32>();
                let val = LittleEndian::read_f32(&grid_buf[start .. ]);
                //println!("val : {}",val);
                val
            }));
    let ef = Vec::from_iter((0..size).map(|i| {
                let offset = size * mem::size_of::<f32>();
                let start = offset + i * mem::size_of::<c32>();
                let val_real = LittleEndian::read_f32(&grid_buf[start                         .. ]);
                let val_imag = LittleEndian::read_f32(&grid_buf[start + mem::size_of::<f32>() .. ]);
                //println!("val_real : {}  val_imag : {}",val_real,val_imag);
                c32::new(val_real, val_imag)
            }));

    (options, ai, ef)
}

fn ef_views(ef: &Vec<c32>) -> (Vec<f32>, Vec<f32>, Vec<f32>) {
    let size = ef.len();
    let ef_re = Vec::from_iter((0..size).map(|i| ef[i].re));
    let ef_im = Vec::from_iter((0..size).map(|i| ef[i].im));
    let ef_as_f32 = Vec::from_iter((0..2*size).map(|i| {
                let j = i/2;
                if i%2 == 0 {ef[j].re} else {ef[j].im}
            }));
    (ef_re, ef_im, ef_as_f32)
}

fn check_kernels_diff(ai: &Vec<f32>, ef_as_f32: &Vec<f32>) -> Vec<f32> {
    let mut ai_copy1 = ai.clone();
    let mut ai_copy2 = ai.clone();
    let size      = ai.len();
    let len       = size as c_int;
    let pai_copy1 = ai_copy1.as_mut_ptr();
    let pai_copy2 = ai_copy2.as_mut_ptr();
    let pef       = ef_as_f32.as_ptr();

    unsafe {
            kernel5(len, pai_copy1, pef);
            kernel7(len, pai_copy2, pef);
    }

    let x: Vec<f32> = ai_copy1.iter()
                .zip( ai_copy2.iter() )
                .map(
                    |(x, y)| (x - y)
                    ).collect();

    x
}

fn main() {

    let (options, mut ai, ef) = cook_input_data(true);
    let size = ai.len();

    let (ef_re, ef_im, ef_as_f32) = ef_views(&ef);

    let rep_count = options.rep_count;

    if options.kernel_num == 9 || options.kernel_num == -1 {
        let timer = timer_start!();

        for _ in 0..rep_count {
            kernel9(&mut ai, &ef);
        }

        timer_stop!(timer, "kernel9");
    }

    if options.kernel_num == 1 || options.kernel_num == -1 {
        let timer = timer_start!();

        for _ in 0..rep_count {
            kernel1(&mut ai, &ef);
        }

        timer_stop!(timer, "kernel1");
    }

    if options.kernel_num == 2 || options.kernel_num == -1 {
        let timer = timer_start!();

        for _ in 0..rep_count {
            kernel2(&mut ai, &ef_re, &ef_im);
        }

        timer_stop!(timer, "kernel2");
    }

    if options.kernel_num == 3 || options.kernel_num == -1 {
        let timer = timer_start!();

        for _ in 0..rep_count {
            kernel3(&mut ai, &ef_as_f32);
        }

        timer_stop!(timer, "kernel3");
    }

    if options.kernel_num == 4 || options.kernel_num == -1 {
        let len = size as c_int;
        let pai = ai.as_mut_ptr();
        let pef = ef_as_f32.as_ptr();
        let timer = timer_start!();

        for _ in 0..rep_count {
            unsafe {
                kernel4(len, pai, pef);
            }
        }

        timer_stop!(timer, "kernel4");
    }

    if options.kernel_num == 5 || options.kernel_num == -1 {
        let len = size as c_int;
        let pai = ai.as_mut_ptr();
        let pef = ef_as_f32.as_ptr();
        let timer = timer_start!();

        for _ in 0..rep_count {
            unsafe {
                kernel5(len, pai, pef);
            }
        }

        timer_stop!(timer, "kernel5");
        if rep_count == 1 {
            println!("output from kernel 5 ai: {:?}", ai);
        }

    }

    if options.kernel_num == 7 || options.kernel_num == -1 {
        let len = size as c_int;
        let pai = ai.as_mut_ptr();
        let pef = ef_as_f32.as_ptr();
        let timer = timer_start!();

        for _ in 0..rep_count {
            unsafe {
                kernel7(len, pai, pef);
            }
        }

        timer_stop!(timer, "kernel7");
        if rep_count == 1 {
            println!("output from kernel 7 ai: {:?}", ai);
        }
    }

    let diff = check_kernels_diff(&ai, &ef_as_f32);
    println!("diff : {:?}",diff);

    println!("fini");
}

#[bench]
fn setup_kernel1(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);

    b.iter(|| {
        kernel1(&mut ai, &ef);
    } )
}

#[bench]
fn setup_kernel2(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);
    let (ef_re, ef_im, _) = ef_views(&ef);

    b.iter(|| {
        kernel2(&mut ai, &ef_re, &ef_im);
    } )
}

#[bench]
fn setup_kernel3(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);
    let (_, _, ef_as_f32) = ef_views(&ef);

    b.iter(|| {
        kernel3(&mut ai, &ef_as_f32);
    } )
}

#[bench]
fn setup_kernel4(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);
    let size = ai.len();

    let (ef_re, ef_im, ef_as_f32) = ef_views(&ef);

    let len = size as c_int;
    let pai = ai.as_mut_ptr();
    let pef = ef_as_f32.as_ptr();

    b.iter(|| {
        unsafe {
            kernel4(len, pai, pef);
        }
    } )
}

#[bench]
fn setup_kernel5(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);
    let size = ai.len();

    let (ef_re, ef_im, ef_as_f32) = ef_views(&ef);

    let len = size as c_int;
    let pai = ai.as_mut_ptr();
    let pef = ef_as_f32.as_ptr();

    b.iter(|| {
        unsafe {
            kernel5(len, pai, pef);
        }
    } )
}

#[bench]
fn setup_kernel6(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);
    let size = ai.len();

    let (ef_re, ef_im, ef_as_f32) = ef_views(&ef);

    let len = size as c_int;
    let pai = ai.as_mut_ptr();
    let pef = ef_as_f32.as_ptr();

    b.iter(|| {
        unsafe {
            kernel6(len, pai, pef);
        }
    } )
}

#[bench]
fn setup_kernel7(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);
    let size = ai.len();

    let (ef_re, ef_im, ef_as_f32) = ef_views(&ef);

    let len = size as c_int;
    let pai = ai.as_mut_ptr();
    let pef = ef_as_f32.as_ptr();

    b.iter(|| {
        unsafe {
            kernel7(len, pai, pef);
        }
    } )
}

#[bench]
fn setup_kernel8(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);

    b.iter(|| {
        ai = kernel8(&ai, &ef);
    } )
}

#[bench]
fn setup_kernel9(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);

    b.iter(|| {
        kernel9(&mut ai, &ef);
    } )
}

<commit_msg>verified sse kernel7 vs. kernel5.<commit_after>#![feature(test)]
extern crate test;

extern crate num;
extern crate byteorder;
extern crate libc;
extern crate argparse;

use test::Bencher;
use std::env;
use std::fs::File;
use std::io::{Read, Write};
use std::io::Cursor;
use std::mem;
use std::iter::FromIterator;
use byteorder::{ByteOrder, LittleEndian, BigEndian, NativeEndian};
use std::time::Duration;
use argparse::{ArgumentParser, StoreTrue, Store};
use std::process::exit;

use libc::{c_int, size_t};
use std::vec;

type c32 = num::Complex<f32>;

macro_rules! timer_start {
    () => {
        {
            let timer = std::time::Instant::now();
            timer
        }
    }
}

macro_rules! timer_stop {
    ($timer:expr, $name:expr) => {
        let d = ($timer).elapsed();
        println!("elapsed time for {}: {:.7}s.", $name, d.as_secs() as f64 + d.subsec_nanos() as f64 / 1.0e9f64);
    }
}

fn kernel1(ai: &mut Vec<f32>, ef: &Vec<c32>) {
    let size = ai.len();
    for i in 0..size {
        ai[i] += ef[i].re.powi(2) + ef[i].im.powi(2);
    }
}

fn kernel2(ai: &mut Vec<f32>, ef_re: &Vec<f32>, ef_im: &Vec<f32>) {
    let size = ai.len();
    for i in 0..size {
        ai[i] += ef_re[i].powi(2) + ef_im[i].powi(2);
    }
}

fn kernel3(ai: &mut Vec<f32>, ef: &Vec<f32>) {
    let size = ai.len();
    for i in 0..size {
        ai[i] += ef[2*i].powi(2) + ef[2*i+1].powi(2);
    }
}

// now play with kernels written in C/C++
#[link(name = "ckernels")]
extern "C" {
    fn kernel4(L: c_int, ai: *mut f32, ef: *const f32);
    fn kernel5(L: c_int, ai: *mut f32, ef: *const f32);
    fn kernel6(L: c_int, ai: *mut f32, ef: *const f32);
    fn kernel7(L: c_int, ai: *mut f32, ef: *const f32);
}

fn kernel8(ai: &Vec<f32>, ef: &Vec<c32>) -> Vec<f32> {
    let x: Vec<f32> = ai.iter()
                .zip( ef.iter() )
                .map(
                    |(x, y)| x + y.re.powi(2) + y.im.powi(2)
                    ).collect();
    x
}

fn kernel9(ai: &mut Vec<f32>, ef: &Vec<c32>) {
    for (x, y) in ai.iter_mut().zip(ef) {
        *x += (*y).re.powi(2) + (*y).im.powi(2);
    }
}

struct Options {
    verbose: bool,
    name: String,
    rep_count: usize,
    kernel_num: isize,
}

fn cook_input_data(parse_options: bool) -> (Options, Vec<f32>, Vec<c32>) {
    let mut options = Options {
        verbose:   false,
        //name:      "./data/add_sum_sq/sum_ef_20077.bin".to_string(),
        name:      "./data/add_sum_sq/sum_ef_20085.bin".to_string(),
        rep_count: 10000,
        kernel_num: -1,
    };

    if parse_options {
        let mut ap = ArgumentParser::new();
        ap.set_description("Time elapsing for add_sum_sq kernels.");
        ap.refer(&mut options.verbose)
            .add_option(&["-v", "--verbose"], StoreTrue,
            "set verbose");
        ap.refer(&mut options.name)
            .add_option(&["-i", "--input"], Store,
            "set name of input file");
        ap.refer(&mut options.rep_count)
            .add_option(&["-n", "--num_iters"], Store,
            "set number of iterations");
        ap.refer(&mut options.kernel_num)
            .add_option(&["-k", "--num_kernel"], Store,
            "set number of kernel");
        match ap.parse_args() {
            Ok(()) => {}
            Err(x) => {
                exit(x);
            }
        }
    }

    if options.verbose {
        println!("input file name : {} number of iterations : {} kernel number : {}",
                 options.name, options.rep_count, options.kernel_num);
    }

    let mut file = File::open(&options.name).ok().expect(&format!("The file {:?} does not exist", &options.name));
    let file_info = file.metadata().ok().expect("Cannot get file metadata");
    if !file_info.is_file() {
        panic!("{:?} is not a file", &options.name);
    }

    if parse_options {
        println!("the file {:?} has length {} bytes", &options.name, file_info.len());
    }

    let mut buf = [0u8; 4];
    file.read(&mut buf[..]);
    let L = LittleEndian::read_u32(&buf[..]);

    if parse_options {
        println!("L : {}", L);
    }

    let size = L as usize;
    let mut grid_buf = Vec::new();
    let sz = file.read_to_end(&mut grid_buf).unwrap();
    let ai = Vec::from_iter((0..size).map(|i| {
                let start = i * mem::size_of::<f32>();
                let val = LittleEndian::read_f32(&grid_buf[start .. ]);
                //println!("val : {}",val);
                val
            }));
    let ef = Vec::from_iter((0..size).map(|i| {
                let offset = size * mem::size_of::<f32>();
                let start = offset + i * mem::size_of::<c32>();
                let val_real = LittleEndian::read_f32(&grid_buf[start                         .. ]);
                let val_imag = LittleEndian::read_f32(&grid_buf[start + mem::size_of::<f32>() .. ]);
                //println!("val_real : {}  val_imag : {}",val_real,val_imag);
                c32::new(val_real, val_imag)
            }));

    (options, ai, ef)
}

fn ef_views(ef: &Vec<c32>) -> (Vec<f32>, Vec<f32>, Vec<f32>) {
    let size = ef.len();
    let ef_re = Vec::from_iter((0..size).map(|i| ef[i].re));
    let ef_im = Vec::from_iter((0..size).map(|i| ef[i].im));
    let ef_as_f32 = Vec::from_iter((0..2*size).map(|i| {
                let j = i/2;
                if i%2 == 0 {ef[j].re} else {ef[j].im}
            }));
    (ef_re, ef_im, ef_as_f32)
}

fn check_kernels_diff(ai: &Vec<f32>, ef_as_f32: &Vec<f32>) -> Vec<f32> {
    let mut ai_copy1 = ai.clone();
    let mut ai_copy2 = ai.clone();
    let size      = ai.len();
    let len       = size as c_int;
    let pai_copy1 = ai_copy1.as_mut_ptr();
    let pai_copy2 = ai_copy2.as_mut_ptr();
    let pef       = ef_as_f32.as_ptr();

    unsafe {
            kernel5(len, pai_copy1, pef);
            kernel7(len, pai_copy2, pef);
    }

    let x: Vec<f32> = ai_copy1.iter()
                .zip( ai_copy2.iter() )
                .map(
                    |(x, y)| (x - y)
                    ).collect();

    x
}

fn main() {

    let (options, mut ai, ef) = cook_input_data(true);
    let size = ai.len();

    let (ef_re, ef_im, ef_as_f32) = ef_views(&ef);

    let rep_count = options.rep_count;

    if options.kernel_num == 9 || options.kernel_num == -1 {
        let timer = timer_start!();

        for _ in 0..rep_count {
            kernel9(&mut ai, &ef);
        }

        timer_stop!(timer, "kernel9");
    }

    if options.kernel_num == 1 || options.kernel_num == -1 {
        let timer = timer_start!();

        for _ in 0..rep_count {
            kernel1(&mut ai, &ef);
        }

        timer_stop!(timer, "kernel1");
    }

    if options.kernel_num == 2 || options.kernel_num == -1 {
        let timer = timer_start!();

        for _ in 0..rep_count {
            kernel2(&mut ai, &ef_re, &ef_im);
        }

        timer_stop!(timer, "kernel2");
    }

    if options.kernel_num == 3 || options.kernel_num == -1 {
        let timer = timer_start!();

        for _ in 0..rep_count {
            kernel3(&mut ai, &ef_as_f32);
        }

        timer_stop!(timer, "kernel3");
    }

    if options.kernel_num == 4 || options.kernel_num == -1 {
        let len = size as c_int;
        let pai = ai.as_mut_ptr();
        let pef = ef_as_f32.as_ptr();
        let timer = timer_start!();

        for _ in 0..rep_count {
            unsafe {
                kernel4(len, pai, pef);
            }
        }

        timer_stop!(timer, "kernel4");
    }

    if options.kernel_num == 5 || options.kernel_num == -1 {
        let len = size as c_int;
        let pai = ai.as_mut_ptr();
        let pef = ef_as_f32.as_ptr();
        let timer = timer_start!();

        for _ in 0..rep_count {
            unsafe {
                kernel5(len, pai, pef);
            }
        }

        timer_stop!(timer, "kernel5");
        if rep_count == 1 {
            println!("output from kernel 5 ai: {:?}", ai);
        }

    }

    if options.kernel_num == 7 || options.kernel_num == -1 {
        let len = size as c_int;
        let pai = ai.as_mut_ptr();
        let pef = ef_as_f32.as_ptr();
        let timer = timer_start!();

        for _ in 0..rep_count {
            unsafe {
                kernel7(len, pai, pef);
            }
        }

        timer_stop!(timer, "kernel7");
        if rep_count == 1 {
            println!("output from kernel 7 ai: {:?}", ai);
        }
    }

    let diff = check_kernels_diff(&ai, &ef_as_f32);
    let mut ind = 0;
    let mut max_diff = 0.0;
    for (i, val) in diff.into_iter().enumerate() {
        println!("{} {:.17}", i, val);
        if val.abs() > max_diff {
            max_diff = val.abs();
            ind = i;
        }
    }
    println!("max_diff : {:.17} ind : {}", max_diff, ind);
    //println!("diff : {:?}",diff);

    println!("fini");
}

#[bench]
fn setup_kernel1(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);

    b.iter(|| {
        kernel1(&mut ai, &ef);
    } )
}

#[bench]
fn setup_kernel2(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);
    let (ef_re, ef_im, _) = ef_views(&ef);

    b.iter(|| {
        kernel2(&mut ai, &ef_re, &ef_im);
    } )
}

#[bench]
fn setup_kernel3(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);
    let (_, _, ef_as_f32) = ef_views(&ef);

    b.iter(|| {
        kernel3(&mut ai, &ef_as_f32);
    } )
}

#[bench]
fn setup_kernel4(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);
    let size = ai.len();

    let (ef_re, ef_im, ef_as_f32) = ef_views(&ef);

    let len = size as c_int;
    let pai = ai.as_mut_ptr();
    let pef = ef_as_f32.as_ptr();

    b.iter(|| {
        unsafe {
            kernel4(len, pai, pef);
        }
    } )
}

#[bench]
fn setup_kernel5(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);
    let size = ai.len();

    let (ef_re, ef_im, ef_as_f32) = ef_views(&ef);

    let len = size as c_int;
    let pai = ai.as_mut_ptr();
    let pef = ef_as_f32.as_ptr();

    b.iter(|| {
        unsafe {
            kernel5(len, pai, pef);
        }
    } )
}

#[bench]
fn setup_kernel6(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);
    let size = ai.len();

    let (ef_re, ef_im, ef_as_f32) = ef_views(&ef);

    let len = size as c_int;
    let pai = ai.as_mut_ptr();
    let pef = ef_as_f32.as_ptr();

    b.iter(|| {
        unsafe {
            kernel6(len, pai, pef);
        }
    } )
}

#[bench]
fn setup_kernel7(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);
    let size = ai.len();

    let (ef_re, ef_im, ef_as_f32) = ef_views(&ef);

    let len = size as c_int;
    let pai = ai.as_mut_ptr();
    let pef = ef_as_f32.as_ptr();

    b.iter(|| {
        unsafe {
            kernel7(len, pai, pef);
        }
    } )
}

#[bench]
fn setup_kernel8(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);

    b.iter(|| {
        ai = kernel8(&ai, &ef);
    } )
}

#[bench]
fn setup_kernel9(b: &mut Bencher) {
    let (_, mut ai, ef) = cook_input_data(false);

    b.iter(|| {
        kernel9(&mut ai, &ef);
    } )
}

<|endoftext|>


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

//! An implementation of base index with most common features.
//!
//! The `BaseIndex` structure is not intended for direct use, rather it is the
//! basis for building other types of indices. The given section contains methods
//! related to `BaseIndex` and the iterator over the items of this index.

// spell-checker:ignore subprefix

use std::{borrow::Cow, marker::PhantomData};

use super::{BinaryKey, BinaryValue, Fork, Iter, Snapshot};
use crate::indexes_metadata::{self, IndexType, INDEXES_METADATA_TABLE_NAME};

/// Basic struct for all indices that implements common features.
///
/// This structure is not intended for direct use, rather it is the basis for building other types
/// of indices.
///
/// `BaseIndex` requires that keys should implement the [`BinaryKey`] trait and
/// values should implement the [`BinaryValue`] trait. However, this structure
/// is not bound to specific types and allows the use of *any* types as keys or values.
///
/// [`BinaryKey`]: ../trait.BinaryKey.html
/// [`BinaryValue`]: ../trait.BinaryValue.html
#[derive(Debug)]
pub struct BaseIndex<T> {
    name: String,
    is_family: bool,
    index_id: Option<Vec<u8>>,
    is_mutable: bool,
    index_type: IndexType,
    view: T,
}

/// An iterator over the entries of a `BaseIndex`.
///
/// This struct is created by the [`iter`] or
/// [`iter_from`] method on [`BaseIndex`]. See its documentation for details.
///
/// [`iter`]: struct.BaseIndex.html#method.iter
/// [`iter_from`]: struct.BaseIndex.html#method.iter_from
/// [`BaseIndex`]: struct.BaseIndex.html
pub struct BaseIndexIter<'a, K, V> {
    base_iter: Iter<'a>,
    base_prefix_len: usize,
    index_id: Vec<u8>,
    ended: bool,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
}

impl<T> BaseIndex<T>
where
    T: AsRef<dyn Snapshot>,
{
    /// Creates a new index representation based on the name and storage view.
    ///
    /// Storage view can be specified as [`&Snapshot`] or [`&mut Fork`]. In the first case, only
    /// immutable methods are available. In the second case, both immutable and mutable methods are
    /// available.
    ///
    /// [`&Snapshot`]: ../trait.Snapshot.html
    /// [`&mut Fork`]: ../struct.Fork.html
    pub fn new<S: AsRef<str>>(index_name: S, index_type: IndexType, view: T) -> Self {
        assert_valid_name(&index_name);

        let is_family = false;
        indexes_metadata::assert_index_type(
            index_name.as_ref(),
            index_type,
            is_family,
            view.as_ref(),
        );

        Self {
            name: index_name.as_ref().to_string(),
            is_family,
            index_id: None,
            is_mutable: false,
            index_type,
            view,
        }
    }

    /// Creates a new index representation based on the family name, index ID inside family
    /// and storage view.
    ///
    /// Storage view can be specified as [`&Snapshot`] or [`&mut Fork`]. In the first case, only
    /// immutable methods are available. In the second case, both immutable and mutable methods are
    /// available.
    ///
    /// [`&Snapshot`]: ../trait.Snapshot.html
    /// [`&mut Fork`]: ../struct.Fork.html
    pub fn new_in_family<S, P>(family_name: S, index_id: &P, index_type: IndexType, view: T) -> Self
    where
        P: BinaryKey,
        P: ?Sized,
        S: AsRef<str>,
    {
        assert_valid_name(&family_name);

        let is_family = true;
        indexes_metadata::assert_index_type(
            family_name.as_ref(),
            index_type,
            is_family,
            view.as_ref(),
        );

        Self {
            name: family_name.as_ref().to_string(),
            is_family,
            index_id: {
                let mut buf = vec![0; index_id.size()];
                index_id.write(&mut buf);
                Some(buf)
            },
            is_mutable: false,
            index_type,
            view,
        }
    }

    pub(crate) fn indexes_metadata(view: T) -> Self {
        Self {
            name: INDEXES_METADATA_TABLE_NAME.to_string(),
            is_family: false,
            index_id: None,
            is_mutable: true,
            index_type: IndexType::Map,
            view,
        }
    }

    fn prefixed_key<K: BinaryKey + ?Sized>(&self, key: &K) -> Vec<u8> {
        if let Some(ref prefix) = self.index_id {
            let mut v = vec![0; prefix.size() + key.size()];
            let pos = prefix.write(&mut v);
            key.write(&mut v[pos..]);
            v
        } else {
            let mut v = vec![0; key.size()];
            key.write(&mut v);
            v
        }
    }

    /// Returns a value of *any* type corresponding to the key of *any* type.
    pub fn get<K, V>(&self, key: &K) -> Option<V>
    where
        K: BinaryKey + ?Sized,
        V: BinaryValue,
    {
        self.view
            .as_ref()
            .get(&self.name, &self.prefixed_key(key))
            .map(get_value)
    }

    /// Returns `true` if the index contains a value of *any* type for the specified key of
    /// *any* type.
    pub fn contains<K>(&self, key: &K) -> bool
    where
        K: BinaryKey + ?Sized,
    {
        self.view
            .as_ref()
            .contains(&self.name, &self.prefixed_key(key))
    }

    /// Returns an iterator over the entries of the index in ascending order. The iterator element
    /// type is *any* key-value pair. An argument `subprefix` allows specifying a subset of keys
    /// for iteration.
    pub fn iter<P, K, V>(&self, subprefix: &P) -> BaseIndexIter<K, V>
    where
        P: BinaryKey,
        K: BinaryKey,
        V: BinaryValue,
    {
        let iter_prefix = self.prefixed_key(subprefix);
        BaseIndexIter {
            base_iter: self.view.as_ref().iter(&self.name, &iter_prefix),
            base_prefix_len: self.index_id.as_ref().map_or(0, |p| p.len()),
            index_id: iter_prefix,
            ended: false,
            _k: PhantomData,
            _v: PhantomData,
        }
    }

    /// Returns an iterator over the entries of the index in ascending order starting from the
    /// specified key. The iterator element type is *any* key-value pair. An argument `subprefix`
    /// allows specifying a subset of iteration.
    pub fn iter_from<P, F, K, V>(&self, subprefix: &P, from: &F) -> BaseIndexIter<K, V>
    where
        P: BinaryKey,
        F: BinaryKey + ?Sized,
        K: BinaryKey,
        V: BinaryValue,
    {
        let iter_prefix = self.prefixed_key(subprefix);
        let iter_from = self.prefixed_key(from);
        BaseIndexIter {
            base_iter: self.view.as_ref().iter(&self.name, &iter_from),
            base_prefix_len: self.index_id.as_ref().map_or(0, |p| p.len()),
            index_id: iter_prefix,
            ended: false,
            _k: PhantomData,
            _v: PhantomData,
        }
    }
}

impl<'a> BaseIndex<&'a mut Fork> {
    fn set_index_type(&mut self) {
        if !self.is_mutable {
            indexes_metadata::set_index_type(
                &self.name,
                self.index_type,
                self.is_family,
                &mut self.view,
            );
            self.is_mutable = true;
        }
    }

    /// Inserts the key-value pair into the index. Both key and value may be of *any* types.
    pub fn put<K, V>(&mut self, key: &K, value: V)
    where
        K: BinaryKey,
        V: BinaryValue,
    {
        self.set_index_type();
        let key = self.prefixed_key(key);
        self.view.put(&self.name, key, value.into_bytes());
    }

    /// Removes the key of *any* type from the index.
    pub fn remove<K>(&mut self, key: &K)
    where
        K: BinaryKey + ?Sized,
    {
        self.set_index_type();
        let key = self.prefixed_key(key);
        self.view.remove(&self.name, key);
    }

    /// Clears the index, removing entries with keys that start with a prefix or all entries
    /// if `prefix` is `None`.
    ///
    /// # Notes
    ///
    /// Currently this method is not optimized to delete a large set of data. During the execution of
    /// this method the amount of allocated memory is linearly dependent on the number of elements
    /// in the index.
    pub fn clear(&mut self) {
        self.set_index_type();
        let prefix = self.index_id.as_ref().map(Vec::as_slice);
        self.view.remove_by_prefix(&self.name, prefix);
    }
}

impl<'a, K, V> Iterator for BaseIndexIter<'a, K, V>
where
    K: BinaryKey,
    V: BinaryValue,
{
    type Item = (K::Owned, V);

    fn next(&mut self) -> Option<Self::Item> {
        if self.ended {
            return None;
        }
        if let Some((k, v)) = self.base_iter.next() {
            if k.starts_with(&self.index_id) {
                return Some((K::read(&k[self.base_prefix_len..]), get_value(v)));
            }
        }
        self.ended = true;
        None
    }
}

impl<'a, K, V> ::std::fmt::Debug for BaseIndexIter<'a, K, V> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "BaseIndexIter(..)")
    }
}

/// Decodes given bytes into the given value.
/// This function panics if the given value can not be decoded from the given buffer.
fn get_value<'a, B, V>(bytes: B) -> V
where
    B: Into<Cow<'a, [u8]>>,
    V: BinaryValue,
{
    let bytes = bytes.into();
    V::from_bytes(bytes).expect("Unable to decode value from bytes, an error occured")
}

/// A function that validates an index name. Allowable characters in name: ASCII characters, digits
/// and underscores.
fn is_valid_name<S: AsRef<str>>(name: S) -> bool {
    name.as_ref().as_bytes().iter().all(|c| match *c {
        48...57 | 65...90 | 97...122 | 95 | 46 => true,
        _ => false,
    })
}

/// Calls the `is_valid_name` function with the given name and panics if it returns `false`.
fn assert_valid_name<S: AsRef<str>>(name: S) {
    if !is_valid_name(name) {
        panic!("Wrong characters using in name. Use: a-zA-Z0-9 and _");
    }
}

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

    #[test]
    fn test_index_name_validator() {
        // spell-checker:disable
        assert!(is_valid_name("index_name"));
        assert!(is_valid_name("_index_name"));
        assert!(is_valid_name("AinDex_name_"));
        assert!(is_valid_name("core.index_name1Z"));
        assert!(is_valid_name("configuration.indeX_1namE"));
        assert!(is_valid_name("1index_Namez"));

        assert!(!is_valid_name("index-name"));
        assert!(!is_valid_name("_index-name"));
        assert!(!is_valid_name("индекс_name_"));
        assert!(!is_valid_name("core.index_имя3"));
        assert!(!is_valid_name("indeX_1namE-"));
        assert!(!is_valid_name("1in!dex_Namez"));
    }

    #[test]
    fn test_check_valid_name() {
        assert_valid_name("valid_name");
    }

    #[test]
    #[should_panic(expected = "Wrong characters using in name. Use: a-zA-Z0-9 and _")]
    fn test_check_invalid_name() {
        assert_valid_name("invalid-name");
    }

    #[test]
    #[should_panic(expected = "Unable to decode value from bytes")]
    fn test_get_value_panic() {
        let wrong_buf = vec![0_u8; 31];
        let _hash: exonum_crypto::Hash = get_value(wrong_buf);
    }
}
<commit_msg>Typo fix<commit_after>// Copyright 2018 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! An implementation of base index with most common features.
//!
//! The `BaseIndex` structure is not intended for direct use, rather it is the
//! basis for building other types of indices. The given section contains methods
//! related to `BaseIndex` and the iterator over the items of this index.

// spell-checker:ignore subprefix

use std::{borrow::Cow, marker::PhantomData};

use super::{BinaryKey, BinaryValue, Fork, Iter, Snapshot};
use crate::indexes_metadata::{self, IndexType, INDEXES_METADATA_TABLE_NAME};

/// Basic struct for all indices that implements common features.
///
/// This structure is not intended for direct use, rather it is the basis for building other types
/// of indices.
///
/// `BaseIndex` requires that keys should implement the [`BinaryKey`] trait and
/// values should implement the [`BinaryValue`] trait. However, this structure
/// is not bound to specific types and allows the use of *any* types as keys or values.
///
/// [`BinaryKey`]: ../trait.BinaryKey.html
/// [`BinaryValue`]: ../trait.BinaryValue.html
#[derive(Debug)]
pub struct BaseIndex<T> {
    name: String,
    is_family: bool,
    index_id: Option<Vec<u8>>,
    is_mutable: bool,
    index_type: IndexType,
    view: T,
}

/// An iterator over the entries of a `BaseIndex`.
///
/// This struct is created by the [`iter`] or
/// [`iter_from`] method on [`BaseIndex`]. See its documentation for details.
///
/// [`iter`]: struct.BaseIndex.html#method.iter
/// [`iter_from`]: struct.BaseIndex.html#method.iter_from
/// [`BaseIndex`]: struct.BaseIndex.html
pub struct BaseIndexIter<'a, K, V> {
    base_iter: Iter<'a>,
    base_prefix_len: usize,
    index_id: Vec<u8>,
    ended: bool,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
}

impl<T> BaseIndex<T>
where
    T: AsRef<dyn Snapshot>,
{
    /// Creates a new index representation based on the name and storage view.
    ///
    /// Storage view can be specified as [`&Snapshot`] or [`&mut Fork`]. In the first case, only
    /// immutable methods are available. In the second case, both immutable and mutable methods are
    /// available.
    ///
    /// [`&Snapshot`]: ../trait.Snapshot.html
    /// [`&mut Fork`]: ../struct.Fork.html
    pub fn new<S: AsRef<str>>(index_name: S, index_type: IndexType, view: T) -> Self {
        assert_valid_name(&index_name);

        let is_family = false;
        indexes_metadata::assert_index_type(
            index_name.as_ref(),
            index_type,
            is_family,
            view.as_ref(),
        );

        Self {
            name: index_name.as_ref().to_string(),
            is_family,
            index_id: None,
            is_mutable: false,
            index_type,
            view,
        }
    }

    /// Creates a new index representation based on the family name, index ID inside family
    /// and storage view.
    ///
    /// Storage view can be specified as [`&Snapshot`] or [`&mut Fork`]. In the first case, only
    /// immutable methods are available. In the second case, both immutable and mutable methods are
    /// available.
    ///
    /// [`&Snapshot`]: ../trait.Snapshot.html
    /// [`&mut Fork`]: ../struct.Fork.html
    pub fn new_in_family<S, P>(family_name: S, index_id: &P, index_type: IndexType, view: T) -> Self
    where
        P: BinaryKey,
        P: ?Sized,
        S: AsRef<str>,
    {
        assert_valid_name(&family_name);

        let is_family = true;
        indexes_metadata::assert_index_type(
            family_name.as_ref(),
            index_type,
            is_family,
            view.as_ref(),
        );

        Self {
            name: family_name.as_ref().to_string(),
            is_family,
            index_id: {
                let mut buf = vec![0; index_id.size()];
                index_id.write(&mut buf);
                Some(buf)
            },
            is_mutable: false,
            index_type,
            view,
        }
    }

    pub(crate) fn indexes_metadata(view: T) -> Self {
        Self {
            name: INDEXES_METADATA_TABLE_NAME.to_string(),
            is_family: false,
            index_id: None,
            is_mutable: true,
            index_type: IndexType::Map,
            view,
        }
    }

    fn prefixed_key<K: BinaryKey + ?Sized>(&self, key: &K) -> Vec<u8> {
        if let Some(ref prefix) = self.index_id {
            let mut v = vec![0; prefix.size() + key.size()];
            let pos = prefix.write(&mut v);
            key.write(&mut v[pos..]);
            v
        } else {
            let mut v = vec![0; key.size()];
            key.write(&mut v);
            v
        }
    }

    /// Returns a value of *any* type corresponding to the key of *any* type.
    pub fn get<K, V>(&self, key: &K) -> Option<V>
    where
        K: BinaryKey + ?Sized,
        V: BinaryValue,
    {
        self.view
            .as_ref()
            .get(&self.name, &self.prefixed_key(key))
            .map(get_value)
    }

    /// Returns `true` if the index contains a value of *any* type for the specified key of
    /// *any* type.
    pub fn contains<K>(&self, key: &K) -> bool
    where
        K: BinaryKey + ?Sized,
    {
        self.view
            .as_ref()
            .contains(&self.name, &self.prefixed_key(key))
    }

    /// Returns an iterator over the entries of the index in ascending order. The iterator element
    /// type is *any* key-value pair. An argument `subprefix` allows specifying a subset of keys
    /// for iteration.
    pub fn iter<P, K, V>(&self, subprefix: &P) -> BaseIndexIter<K, V>
    where
        P: BinaryKey,
        K: BinaryKey,
        V: BinaryValue,
    {
        let iter_prefix = self.prefixed_key(subprefix);
        BaseIndexIter {
            base_iter: self.view.as_ref().iter(&self.name, &iter_prefix),
            base_prefix_len: self.index_id.as_ref().map_or(0, |p| p.len()),
            index_id: iter_prefix,
            ended: false,
            _k: PhantomData,
            _v: PhantomData,
        }
    }

    /// Returns an iterator over the entries of the index in ascending order starting from the
    /// specified key. The iterator element type is *any* key-value pair. An argument `subprefix`
    /// allows specifying a subset of iteration.
    pub fn iter_from<P, F, K, V>(&self, subprefix: &P, from: &F) -> BaseIndexIter<K, V>
    where
        P: BinaryKey,
        F: BinaryKey + ?Sized,
        K: BinaryKey,
        V: BinaryValue,
    {
        let iter_prefix = self.prefixed_key(subprefix);
        let iter_from = self.prefixed_key(from);
        BaseIndexIter {
            base_iter: self.view.as_ref().iter(&self.name, &iter_from),
            base_prefix_len: self.index_id.as_ref().map_or(0, |p| p.len()),
            index_id: iter_prefix,
            ended: false,
            _k: PhantomData,
            _v: PhantomData,
        }
    }
}

impl<'a> BaseIndex<&'a mut Fork> {
    fn set_index_type(&mut self) {
        if !self.is_mutable {
            indexes_metadata::set_index_type(
                &self.name,
                self.index_type,
                self.is_family,
                &mut self.view,
            );
            self.is_mutable = true;
        }
    }

    /// Inserts the key-value pair into the index. Both key and value may be of *any* types.
    pub fn put<K, V>(&mut self, key: &K, value: V)
    where
        K: BinaryKey,
        V: BinaryValue,
    {
        self.set_index_type();
        let key = self.prefixed_key(key);
        self.view.put(&self.name, key, value.into_bytes());
    }

    /// Removes the key of *any* type from the index.
    pub fn remove<K>(&mut self, key: &K)
    where
        K: BinaryKey + ?Sized,
    {
        self.set_index_type();
        let key = self.prefixed_key(key);
        self.view.remove(&self.name, key);
    }

    /// Clears the index, removing entries with keys that start with a prefix or all entries
    /// if `prefix` is `None`.
    ///
    /// # Notes
    ///
    /// Currently this method is not optimized to delete a large set of data. During the execution of
    /// this method the amount of allocated memory is linearly dependent on the number of elements
    /// in the index.
    pub fn clear(&mut self) {
        self.set_index_type();
        let prefix = self.index_id.as_ref().map(Vec::as_slice);
        self.view.remove_by_prefix(&self.name, prefix);
    }
}

impl<'a, K, V> Iterator for BaseIndexIter<'a, K, V>
where
    K: BinaryKey,
    V: BinaryValue,
{
    type Item = (K::Owned, V);

    fn next(&mut self) -> Option<Self::Item> {
        if self.ended {
            return None;
        }
        if let Some((k, v)) = self.base_iter.next() {
            if k.starts_with(&self.index_id) {
                return Some((K::read(&k[self.base_prefix_len..]), get_value(v)));
            }
        }
        self.ended = true;
        None
    }
}

impl<'a, K, V> ::std::fmt::Debug for BaseIndexIter<'a, K, V> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "BaseIndexIter(..)")
    }
}

/// Decodes given bytes into the given value.
/// This function panics if the given value can not be decoded from the given buffer.
fn get_value<'a, B, V>(bytes: B) -> V
where
    B: Into<Cow<'a, [u8]>>,
    V: BinaryValue,
{
    let bytes = bytes.into();
    V::from_bytes(bytes).expect("Unable to decode value from bytes, an error occurred")
}

/// A function that validates an index name. Allowable characters in name: ASCII characters, digits
/// and underscores.
fn is_valid_name<S: AsRef<str>>(name: S) -> bool {
    name.as_ref().as_bytes().iter().all(|c| match *c {
        48...57 | 65...90 | 97...122 | 95 | 46 => true,
        _ => false,
    })
}

/// Calls the `is_valid_name` function with the given name and panics if it returns `false`.
fn assert_valid_name<S: AsRef<str>>(name: S) {
    if !is_valid_name(name) {
        panic!("Wrong characters using in name. Use: a-zA-Z0-9 and _");
    }
}

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

    #[test]
    fn test_index_name_validator() {
        // spell-checker:disable
        assert!(is_valid_name("index_name"));
        assert!(is_valid_name("_index_name"));
        assert!(is_valid_name("AinDex_name_"));
        assert!(is_valid_name("core.index_name1Z"));
        assert!(is_valid_name("configuration.indeX_1namE"));
        assert!(is_valid_name("1index_Namez"));

        assert!(!is_valid_name("index-name"));
        assert!(!is_valid_name("_index-name"));
        assert!(!is_valid_name("индекс_name_"));
        assert!(!is_valid_name("core.index_имя3"));
        assert!(!is_valid_name("indeX_1namE-"));
        assert!(!is_valid_name("1in!dex_Namez"));
    }

    #[test]
    fn test_check_valid_name() {
        assert_valid_name("valid_name");
    }

    #[test]
    #[should_panic(expected = "Wrong characters using in name. Use: a-zA-Z0-9 and _")]
    fn test_check_invalid_name() {
        assert_valid_name("invalid-name");
    }

    #[test]
    #[should_panic(expected = "Unable to decode value from bytes")]
    fn test_get_value_panic() {
        let wrong_buf = vec![0_u8; 31];
        let _hash: exonum_crypto::Hash = get_value(wrong_buf);
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

use cargo_registry::{boot, App, Env};
use jemalloc_ctl;
use std::{
    env,
    fs::File,
    sync::{mpsc::channel, Arc},
};

use civet::Server as CivetServer;
use conduit_hyper::Service as HyperService;

enum Server {
    Civet(CivetServer),
    Hyper(HyperService<conduit_middleware::MiddlewareBuilder>),
}

use Server::*;

fn main() {
    let _ = jemalloc_ctl::set_background_thread(true);

    // Initialize logging
    env_logger::init();

    let config = cargo_registry::Config::default();
    let app = App::new(&config);
    let app = cargo_registry::build_handler(Arc::new(app));

    // On every server restart, ensure the categories available in the database match
    // the information in *src/categories.toml*.
    let categories_toml = include_str!("../boot/categories.toml");
    boot::categories::sync(categories_toml).unwrap();

    let heroku = env::var("HEROKU").is_ok();
    let port = if heroku {
        8888
    } else {
        env::var("PORT")
            .ok()
            .and_then(|s| s.parse().ok())
            .unwrap_or(8888)
    };
    let threads = if config.env == Env::Development {
        1
    } else {
        50
    };

    let server = if env::var("USE_HYPER").is_ok() {
        println!("Booting with a hyper based server");
        Hyper(HyperService::new(app, threads as usize))
    } else {
        println!("Booting with a civet based server");
        let mut cfg = civet::Config::new();
        cfg.port(port).threads(threads).keep_alive(true);
        Civet(CivetServer::start(cfg, app).unwrap())
    };

    println!("listening on port {}", port);

    // Creating this file tells heroku to tell nginx that the application is ready
    // to receive traffic.
    if heroku {
        File::create("/tmp/app-initialized").unwrap();
    }

    if let Hyper(server) = server {
        let addr = ([127, 0, 0, 1], port).into();
        server.run(addr);
    } else {
        // Civet server is already running, but we need to block the main thread forever
        // TODO: handle a graceful shutdown by just waiting for a SIG{INT,TERM}
        let (_tx, rx) = channel::<()>();
        rx.recv().unwrap();
    }
}
<commit_msg>Auto merge of #1666 - sgrif:sg-configurable-server-threads, r=jtgeibel<commit_after>#![deny(warnings)]

use cargo_registry::{boot, App, Env};
use jemalloc_ctl;
use std::{
    env,
    fs::File,
    sync::{mpsc::channel, Arc},
};

use civet::Server as CivetServer;
use conduit_hyper::Service as HyperService;

enum Server {
    Civet(CivetServer),
    Hyper(HyperService<conduit_middleware::MiddlewareBuilder>),
}

use Server::*;

fn main() {
    let _ = jemalloc_ctl::set_background_thread(true);

    // Initialize logging
    env_logger::init();

    let config = cargo_registry::Config::default();
    let app = App::new(&config);
    let app = cargo_registry::build_handler(Arc::new(app));

    // On every server restart, ensure the categories available in the database match
    // the information in *src/categories.toml*.
    let categories_toml = include_str!("../boot/categories.toml");
    boot::categories::sync(categories_toml).unwrap();

    let heroku = env::var("HEROKU").is_ok();
    let port = if heroku {
        8888
    } else {
        env::var("PORT")
            .ok()
            .and_then(|s| s.parse().ok())
            .unwrap_or(8888)
    };
    let threads = env::var("SERVER_THREADS")
        .map(|s| s.parse().expect("SERVER_THREADS was not a valid number"))
        .unwrap_or_else(|_| {
            if config.env == Env::Development {
                1
            } else {
                50
            }
        });

    let server = if env::var("USE_HYPER").is_ok() {
        println!("Booting with a hyper based server");
        Hyper(HyperService::new(app, threads as usize))
    } else {
        println!("Booting with a civet based server");
        let mut cfg = civet::Config::new();
        cfg.port(port).threads(threads).keep_alive(true);
        Civet(CivetServer::start(cfg, app).unwrap())
    };

    println!("listening on port {}", port);

    // Creating this file tells heroku to tell nginx that the application is ready
    // to receive traffic.
    if heroku {
        File::create("/tmp/app-initialized").unwrap();
    }

    if let Hyper(server) = server {
        let addr = ([127, 0, 0, 1], port).into();
        server.run(addr);
    } else {
        // Civet server is already running, but we need to block the main thread forever
        // TODO: handle a graceful shutdown by just waiting for a SIG{INT,TERM}
        let (_tx, rx) = channel::<()>();
        rx.recv().unwrap();
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Non-arch-specific paging.
use memory::{VAddr, PAddr};
use arch::memory::{ PAGE_SHIFT, PAGE_SIZE };

/// Trait for a memory allocator which can allocate memory in terms of frames.
pub trait FrameAllocator<Frame> {

    /// Allocate a new `Frame`
    //  TODO: do we want to be able to request a frame size?
    fn alloc_frame(&mut self) -> Option<Frame>;

    /// Deallocate a given `Frame`.
    fn dealloc_frame(&mut self, frame: Frame);
}

pub trait Mapper {
    type Flags;
    type Frame;

    /// Translates a virtual address to the corresponding physical address.
    ///
    /// # Return
    ///  + `Some(PAddr)` containing the physical address corresponding to
    ///       `vaddr`, if it is mapped.
    ///  + `None`: if the address is not mapped.
    fn translate(&self, vaddr: VAddr) -> Option<PAddr>;

    /// Translates a virtual page to a physical frame.
    fn translate_page(&self, page: Page) -> Option<Self::Frame>;

    /// Modifies the page tables so that `page` maps to `frame`.
    ///
    /// # Arguments
    /// + `page`: the virtual `Page` to map
    /// + `frame`: the physical `Frame` that `Page` should map to.
    /// + `flags`: the page table entry flags.
    /// + `alloc`: a memory allocator
    fn map_to<A>( &mut self, page: Page, frame: Self::Frame
                , flags: Self::Flags, alloc: &mut A )
    where A: FrameAllocator<Self::Frame>;

    /// Identity map a given `frame`.
    ///
    /// # Arguments
    /// + `frame`: the physical `Frame` to identity map
    /// + `flags`: the page table entry flags.
    /// + `alloc`: a memory allocator
    fn identity_map<A>( &mut self, frame: Self::Frame
                      , flags: Self::Flags, alloc: &mut A )
    where A: FrameAllocator<Self::Frame>;

    /// Map the given `page` to any free frame.
    ///
    /// This is like the fire and forget version of `map_to`: we just pick the
    /// first available free frame and map the page to it.
    ///
    /// # Arguments
    /// + `page`: the virtual `Page` to map
    /// + `flags`: the page table entry flags.
    /// + `alloc`: a memory allocator
    fn map_to_any<A>(&mut self, page: Page, flags: Self::Flags, alloc: &mut A)
    where A: FrameAllocator<Self::Frame>;

}

macro_rules! table_idx {
    ( $($name:ident >> $shift:expr)* ) => {$(
        pub fn $name(&self) -> usize {
            (self.number >> $shift) & 0o777
        }
    )*};
}

/// A virtual page
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Page { pub number: usize }

impl Page {
    /// Create a new `Page` containing the given virtual address.
    //  TODO: rewrite this as `up`/`down` using the page shift, instead.
    pub fn containing(addr: VAddr) -> Page {
        assert!( *addr < 0x0000_8000_0000_0000 ||
                 *addr >= 0xffff_8000_0000_0000
               , "invalid address: 0x{:x}", addr );
        Page { number: *addr / PAGE_SIZE as usize }
    }

    /// Return the start virtual address of this page
    #[inline]
    pub fn base_addr(&self) -> VAddr {
        VAddr::from(self.number << PAGE_SHIFT)
    }

    /// Flush the page from memory
    pub unsafe fn flush(&self) {
        asm!( "invlpg [$0]"
            :
            : "{rax}"(self.base_addr())
            : "memory"
            : "intel", "volatile")
    }

    table_idx!{
        pml4_index >> 27
        pdpt_index >> 18
        pd_index >> 9
        pt_index >> 0
    }

    /// Returns a `PageRange`
    pub const fn range_between(start: Page, end: Page) -> PageRange {
        PageRange { start: start, end: end }
    }

    /// Returns a `PageRange` on the pages from this page until the end page
    pub const fn range_until(&self, end: Page) -> PageRange {
        PageRange { start: *self, end: end }
    }

}

/// A range of pages
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct PageRange { start: Page, end: Page }

impl PageRange {
    /// Returns an iterator over this `PageRange`
    pub fn iter<'a>(&'a self) -> PageRangeIter<'a> {
        PageRangeIter { range: self, current: self.start.clone() }
    }
}

/// An iterator over a range of pages
pub struct PageRangeIter<'a> { range: &'a PageRange, current: Page }

impl<'a> Iterator for PageRangeIter<'a> {
    type Item = Page;

    fn next(&mut self) -> Option<Page> {
      let end = self.range.end.number;
      assert!(self.range.start.number <= end);
      if self.current.number < end {
          let page = self.current.clone();
          self.current.number += 1;
          Some(page)
      } else {
          None
      }
  }

}
<commit_msg>[notes]<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Non-arch-specific paging.
use memory::{VAddr, PAddr};
use arch::memory::{ PAGE_SHIFT, PAGE_SIZE };

/// Trait for a memory allocator which can allocate memory in terms of frames.
pub trait FrameAllocator<Frame> {

    /// Allocate a new `Frame`
    //  TODO: do we want to be able to request a frame size?
    fn alloc_frame(&mut self) -> Option<Frame>;

    /// Deallocate a given `Frame`.
    fn dealloc_frame(&mut self, frame: Frame);
}

pub trait Mapper {
    type Flags;
    type Frame;

    /// Translates a virtual address to the corresponding physical address.
    ///
    /// # Return
    ///  + `Some(PAddr)` containing the physical address corresponding to
    ///       `vaddr`, if it is mapped.
    ///  + `None`: if the address is not mapped.
    fn translate(&self, vaddr: VAddr) -> Option<PAddr>;

    /// Translates a virtual page to a physical frame.
    fn translate_page(&self, page: Page) -> Option<Self::Frame>;

    /// Modifies the page tables so that `page` maps to `frame`.
    ///
    /// # Arguments
    /// + `page`: the virtual `Page` to map
    /// + `frame`: the physical `Frame` that `Page` should map to.
    /// + `flags`: the page table entry flags.
    /// + `alloc`: a memory allocator
    fn map_to<A>( &mut self, page: Page, frame: Self::Frame
                , flags: Self::Flags, alloc: &mut A )
    where A: FrameAllocator<Self::Frame>;

    /// Identity map a given `frame`.
    ///
    /// # Arguments
    /// + `frame`: the physical `Frame` to identity map
    /// + `flags`: the page table entry flags.
    /// + `alloc`: a memory allocator
    fn identity_map<A>( &mut self, frame: Self::Frame
                      , flags: Self::Flags, alloc: &mut A )
    where A: FrameAllocator<Self::Frame>;

    /// Map the given `page` to any free frame.
    ///
    /// This is like the fire and forget version of `map_to`: we just pick the
    /// first available free frame and map the page to it.
    ///
    /// # Arguments
    /// + `page`: the virtual `Page` to map
    /// + `flags`: the page table entry flags.
    /// + `alloc`: a memory allocator
    fn map_to_any<A>(&mut self, page: Page, flags: Self::Flags, alloc: &mut A)
    where A: FrameAllocator<Self::Frame>;

}

macro_rules! table_idx {
    ( $($name:ident >> $shift:expr)* ) => {$(
        pub fn $name(&self) -> usize {
            (self.number >> $shift) & 0o777
        }
    )*};
}

/// A virtual page
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Page { pub number: usize }

impl Page {
    /// Create a new `Page` containing the given virtual address.
    //  TODO: rewrite this as `up`/`down` using the page shift, instead.
    pub fn containing(addr: VAddr) -> Page {
        assert!( *addr < 0x0000_8000_0000_0000 ||
                 *addr >= 0xffff_8000_0000_0000
               , "invalid address: 0x{:x}", addr );
        Page { number: *addr / PAGE_SIZE as usize }
    }

    /// Return the start virtual address of this page
    #[inline]
    pub fn base_addr(&self) -> VAddr {
        VAddr::from(self.number << PAGE_SHIFT)
    }

    /// Flush the page from memory
    //  TODO: this is arch-specific, move it to arch
    pub unsafe fn flush(&self) {
        asm!( "invlpg [$0]"
            :
            : "{rax}"(self.base_addr())
            : "memory"
            : "intel", "volatile")
    }

    // TODO: these are arch-specific, move them to `arch`
    table_idx!{
        pml4_index >> 27
        pdpt_index >> 18
        pd_index >> 9
        pt_index >> 0
    }

    /// Returns a `PageRange`
    pub const fn range_between(start: Page, end: Page) -> PageRange {
        PageRange { start: start, end: end }
    }

    /// Returns a `PageRange` on the pages from this page until the end page
    pub const fn range_until(&self, end: Page) -> PageRange {
        PageRange { start: *self, end: end }
    }

}

/// A range of pages
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct PageRange { start: Page, end: Page }

impl PageRange {
    /// Returns an iterator over this `PageRange`
    pub fn iter<'a>(&'a self) -> PageRangeIter<'a> {
        PageRangeIter { range: self, current: self.start.clone() }
    }
}

/// An iterator over a range of pages
pub struct PageRangeIter<'a> { range: &'a PageRange, current: Page }

impl<'a> Iterator for PageRangeIter<'a> {
    type Item = Page;

    fn next(&mut self) -> Option<Page> {
      let end = self.range.end.number;
      assert!(self.range.start.number <= end);
      if self.current.number < end {
          let page = self.current.clone();
          self.current.number += 1;
          Some(page)
      } else {
          None
      }
  }

}
<|endoftext|>