<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex, Complex32, Complex64};
use attribute::{Diagonal, Side, Symmetry};
use pointer::CPtr;
use scalar::Scalar;
use matrix;
use matrix::BlasMatrix;
use vector::BlasVector;

pub trait Gemm {
    fn gemm(alpha: Self, a: &BlasMatrix<Self>, b: &BlasMatrix<Self>, beta: Self, c: &mut BlasMatrix<Self>);
}

macro_rules! gemm_impl(
    ($t: ty, $gemm_fn: ident) => (
        impl Gemm for $t {
            fn gemm(alpha: $t, a: &BlasMatrix<$t>, b: &BlasMatrix<$t>, beta: $t, c: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix::ll::$gemm_fn(a.order(),
                        a.transpose(), b.transpose(),
                        a.rows(), b.cols(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        b.as_ptr().as_c_ptr(), b.lead_dim(),
                        (&beta).as_const(),
                        c.as_mut_ptr().as_c_ptr(), c.lead_dim());
                }
            }
        }
    );
)

gemm_impl!(f32,       cblas_sgemm)
gemm_impl!(f64,       cblas_dgemm)
gemm_impl!(Complex32, cblas_cgemm)
gemm_impl!(Complex64, cblas_zgemm)

pub trait Symm {
    fn symm(side: Side, symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, b: &BlasMatrix<Self>, beta: Self, c: &mut BlasMatrix<Self>);
}

pub trait Hemm {
    fn hemm(side: Side, symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, b: &BlasMatrix<Self>, beta: Self, c: &mut BlasMatrix<Self>);
}

macro_rules! symm_impl(
    ($trait_name: ident, $fn_name: ident, $t: ty, $symm_fn: ident) => (
        impl $trait_name for $t {
            fn $fn_name(side: Side, symmetry: Symmetry, alpha: $t, a: &BlasMatrix<$t>, b: &BlasMatrix<$t>, beta: $t, c: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix::ll::$symm_fn(a.order(),
                        side, symmetry,
                        a.rows(), b.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        b.as_ptr().as_c_ptr(), b.lead_dim(),
                        (&beta).as_const(),
                        c.as_mut_ptr().as_c_ptr(), c.lead_dim());
                }
            }
        }
    );
)

symm_impl!(Symm, symm, f32,       cblas_ssymm)
symm_impl!(Symm, symm, f64,       cblas_dsymm)
symm_impl!(Symm, symm, Complex32, cblas_csymm)
symm_impl!(Symm, symm, Complex64, cblas_zsymm)

symm_impl!(Hemm, hemm, Complex32, cblas_chemm)
symm_impl!(Hemm, hemm, Complex64, cblas_zhemm)

pub trait Trmm {
    fn trmm(side: Side, symmetry: Symmetry, diag: Diagonal, alpha: Self, a: &BlasMatrix<Self>, b: &mut BlasMatrix<Self>);
}

pub trait Trsm {
    fn trsm(side: Side, symmetry: Symmetry, diag: Diagonal, alpha: Self, a: &BlasMatrix<Self>, b: &mut BlasMatrix<Self>);
}

macro_rules! trmm_impl(
    ($trait_name: ident, $fn_name: ident, $t: ty, $symm_fn: ident) => (
        impl $trait_name for $t {
            fn $fn_name(side: Side, symmetry: Symmetry, diag: Diagonal, alpha: $t, a: &BlasMatrix<$t>, b: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix::ll::$symm_fn(a.order(),
                        side, symmetry, a.transpose(), diag,
                        b.rows(), b.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        b.as_mut_ptr().as_c_ptr(), b.lead_dim());
                }
            }
        }
    );
)

trmm_impl!(Trmm, trmm, f32,       cblas_strmm)
trmm_impl!(Trmm, trmm, f64,       cblas_dtrmm)
trmm_impl!(Trmm, trmm, Complex32, cblas_ctrmm)
trmm_impl!(Trmm, trmm, Complex64, cblas_ztrmm)

trmm_impl!(Trsm, trsm, Complex32, cblas_ctrsm)
trmm_impl!(Trsm, trsm, Complex64, cblas_ztrsm)

pub trait Herk {
    fn herk(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Complex<Self>>, beta: Self, c: &mut BlasMatrix<Complex<Self>>);
}

macro_rules! herk_impl(
    ($t: ty, $symm_fn: ident) => (
        impl Herk for $t {
            fn herk(symmetry: Symmetry, alpha: $t, a: &BlasMatrix<Complex<$t>>, beta: $t, c: &mut BlasMatrix<Complex<$t>>) {
                unsafe {
                    matrix::ll::$symm_fn(a.order(),
                        symmetry, a.transpose(),
                        a.rows(), a.cols(),
                        alpha,
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        beta,
                        c.as_mut_ptr().as_c_ptr(), c.lead_dim());
                }
            }
        }
    );
)

herk_impl!(f32, cblas_cherk)
herk_impl!(f64, cblas_zherk)

pub trait Her2k {
    fn her2k(symmetry: Symmetry, alpha: Complex<Self>, a: &BlasMatrix<Complex<Self>>, b: &BlasMatrix<Complex<Self>>, beta: Self, c: &mut BlasMatrix<Complex<Self>>);
}

macro_rules! her2k_impl(
    ($t: ty, $her2k_fn: ident) => (
        impl Her2k for $t {
            fn her2k(symmetry: Symmetry, alpha: Complex<$t>, a: &BlasMatrix<Complex<$t>>, b: &BlasMatrix<Complex<$t>>, beta: $t, c: &mut BlasMatrix<Complex<$t>>) {
                unsafe {
                    matrix::ll::$her2k_fn(a.order(),
                        symmetry, a.transpose(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        b.as_ptr().as_c_ptr(), b.lead_dim(),
                        beta,
                        c.as_mut_ptr().as_c_ptr(), c.lead_dim());
                }
            }
        }
    );
)

her2k_impl!(f32, cblas_cher2k)
her2k_impl!(f64, cblas_zher2k)

pub trait Syrk {
    fn syrk(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, beta: Self, c: &mut BlasMatrix<Self>);
}

macro_rules! syrk_impl(
    ($t: ty, $symm_fn: ident) => (
        impl Syrk for $t {
            fn syrk(symmetry: Symmetry, alpha: $t, a: &BlasMatrix<$t>, beta: $t, c: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix::ll::$symm_fn(a.order(),
                        symmetry, a.transpose(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        (&beta).as_const(),
                        c.as_mut_ptr().as_c_ptr(), c.lead_dim());
                }
            }
        }
    );
)

syrk_impl!(f32,       cblas_ssyrk)
syrk_impl!(f64,       cblas_dsyrk)
syrk_impl!(Complex32, cblas_csyrk)
syrk_impl!(Complex64, cblas_zsyrk)
<commit_msg>Add Syr2k trait<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex, Complex32, Complex64};
use attribute::{Diagonal, Side, Symmetry};
use pointer::CPtr;
use scalar::Scalar;
use matrix;
use matrix::BlasMatrix;
use vector::BlasVector;

pub trait Gemm {
    fn gemm(alpha: Self, a: &BlasMatrix<Self>, b: &BlasMatrix<Self>, beta: Self, c: &mut BlasMatrix<Self>);
}

macro_rules! gemm_impl(
    ($t: ty, $gemm_fn: ident) => (
        impl Gemm for $t {
            fn gemm(alpha: $t, a: &BlasMatrix<$t>, b: &BlasMatrix<$t>, beta: $t, c: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix::ll::$gemm_fn(a.order(),
                        a.transpose(), b.transpose(),
                        a.rows(), b.cols(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        b.as_ptr().as_c_ptr(), b.lead_dim(),
                        (&beta).as_const(),
                        c.as_mut_ptr().as_c_ptr(), c.lead_dim());
                }
            }
        }
    );
)

gemm_impl!(f32,       cblas_sgemm)
gemm_impl!(f64,       cblas_dgemm)
gemm_impl!(Complex32, cblas_cgemm)
gemm_impl!(Complex64, cblas_zgemm)

pub trait Symm {
    fn symm(side: Side, symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, b: &BlasMatrix<Self>, beta: Self, c: &mut BlasMatrix<Self>);
}

pub trait Hemm {
    fn hemm(side: Side, symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, b: &BlasMatrix<Self>, beta: Self, c: &mut BlasMatrix<Self>);
}

macro_rules! symm_impl(
    ($trait_name: ident, $fn_name: ident, $t: ty, $symm_fn: ident) => (
        impl $trait_name for $t {
            fn $fn_name(side: Side, symmetry: Symmetry, alpha: $t, a: &BlasMatrix<$t>, b: &BlasMatrix<$t>, beta: $t, c: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix::ll::$symm_fn(a.order(),
                        side, symmetry,
                        a.rows(), b.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        b.as_ptr().as_c_ptr(), b.lead_dim(),
                        (&beta).as_const(),
                        c.as_mut_ptr().as_c_ptr(), c.lead_dim());
                }
            }
        }
    );
)

symm_impl!(Symm, symm, f32,       cblas_ssymm)
symm_impl!(Symm, symm, f64,       cblas_dsymm)
symm_impl!(Symm, symm, Complex32, cblas_csymm)
symm_impl!(Symm, symm, Complex64, cblas_zsymm)

symm_impl!(Hemm, hemm, Complex32, cblas_chemm)
symm_impl!(Hemm, hemm, Complex64, cblas_zhemm)

pub trait Trmm {
    fn trmm(side: Side, symmetry: Symmetry, diag: Diagonal, alpha: Self, a: &BlasMatrix<Self>, b: &mut BlasMatrix<Self>);
}

pub trait Trsm {
    fn trsm(side: Side, symmetry: Symmetry, diag: Diagonal, alpha: Self, a: &BlasMatrix<Self>, b: &mut BlasMatrix<Self>);
}

macro_rules! trmm_impl(
    ($trait_name: ident, $fn_name: ident, $t: ty, $symm_fn: ident) => (
        impl $trait_name for $t {
            fn $fn_name(side: Side, symmetry: Symmetry, diag: Diagonal, alpha: $t, a: &BlasMatrix<$t>, b: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix::ll::$symm_fn(a.order(),
                        side, symmetry, a.transpose(), diag,
                        b.rows(), b.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        b.as_mut_ptr().as_c_ptr(), b.lead_dim());
                }
            }
        }
    );
)

trmm_impl!(Trmm, trmm, f32,       cblas_strmm)
trmm_impl!(Trmm, trmm, f64,       cblas_dtrmm)
trmm_impl!(Trmm, trmm, Complex32, cblas_ctrmm)
trmm_impl!(Trmm, trmm, Complex64, cblas_ztrmm)

trmm_impl!(Trsm, trsm, Complex32, cblas_ctrsm)
trmm_impl!(Trsm, trsm, Complex64, cblas_ztrsm)

pub trait Herk {
    fn herk(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Complex<Self>>, beta: Self, c: &mut BlasMatrix<Complex<Self>>);
}

macro_rules! herk_impl(
    ($t: ty, $symm_fn: ident) => (
        impl Herk for $t {
            fn herk(symmetry: Symmetry, alpha: $t, a: &BlasMatrix<Complex<$t>>, beta: $t, c: &mut BlasMatrix<Complex<$t>>) {
                unsafe {
                    matrix::ll::$symm_fn(a.order(),
                        symmetry, a.transpose(),
                        a.rows(), a.cols(),
                        alpha,
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        beta,
                        c.as_mut_ptr().as_c_ptr(), c.lead_dim());
                }
            }
        }
    );
)

herk_impl!(f32, cblas_cherk)
herk_impl!(f64, cblas_zherk)

pub trait Her2k {
    fn her2k(symmetry: Symmetry, alpha: Complex<Self>, a: &BlasMatrix<Complex<Self>>, b: &BlasMatrix<Complex<Self>>, beta: Self, c: &mut BlasMatrix<Complex<Self>>);
}

macro_rules! her2k_impl(
    ($t: ty, $her2k_fn: ident) => (
        impl Her2k for $t {
            fn her2k(symmetry: Symmetry, alpha: Complex<$t>, a: &BlasMatrix<Complex<$t>>, b: &BlasMatrix<Complex<$t>>, beta: $t, c: &mut BlasMatrix<Complex<$t>>) {
                unsafe {
                    matrix::ll::$her2k_fn(a.order(),
                        symmetry, a.transpose(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        b.as_ptr().as_c_ptr(), b.lead_dim(),
                        beta,
                        c.as_mut_ptr().as_c_ptr(), c.lead_dim());
                }
            }
        }
    );
)

her2k_impl!(f32, cblas_cher2k)
her2k_impl!(f64, cblas_zher2k)

pub trait Syrk {
    fn syrk(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, beta: Self, c: &mut BlasMatrix<Self>);
}

macro_rules! syrk_impl(
    ($t: ty, $symm_fn: ident) => (
        impl Syrk for $t {
            fn syrk(symmetry: Symmetry, alpha: $t, a: &BlasMatrix<$t>, beta: $t, c: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix::ll::$symm_fn(a.order(),
                        symmetry, a.transpose(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        (&beta).as_const(),
                        c.as_mut_ptr().as_c_ptr(), c.lead_dim());
                }
            }
        }
    );
)

syrk_impl!(f32,       cblas_ssyrk)
syrk_impl!(f64,       cblas_dsyrk)
syrk_impl!(Complex32, cblas_csyrk)
syrk_impl!(Complex64, cblas_zsyrk)

pub trait Syr2k {
    fn syr2k(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, b: &BlasMatrix<Self>, beta: Self, c: &mut BlasMatrix<Self>);
}

macro_rules! syr2k_impl(
    ($t: ty, $syr2k_fn: ident) => (
        impl Syr2k for $t {
            fn syr2k(symmetry: Symmetry, alpha: $t, a: &BlasMatrix<$t>, b: &BlasMatrix<$t>, beta: $t, c: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix::ll::$syr2k_fn(a.order(),
                        symmetry, a.transpose(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        b.as_ptr().as_c_ptr(), b.lead_dim(),
                        (&beta).as_const(),
                        c.as_mut_ptr().as_c_ptr(), c.lead_dim());
                }
            }
        }
    );
)

syr2k_impl!(f32,       cblas_ssyr2k)
syr2k_impl!(f64,       cblas_dsyr2k)
syr2k_impl!(Complex32, cblas_csyr2k)
syr2k_impl!(Complex64, cblas_zsyr2k)
<|endoftext|>


<commit_before>use std::sync::{RwLock, RwLockWriteGuard};
use std::error::Error;

use iron::prelude::*;
use iron::status;
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use plugin::Plugin as PluginFor;
use iron::headers::ContentType;

use handlebars::{Handlebars, TemplateRenderError};
#[cfg(not(feature = "serde_type"))]
use serialize::json::{ToJson, Json};
#[cfg(feature = "serde_type")]
use serde::ser::Serialize as ToJson;
#[cfg(feature = "serde_type")]
use serde_json::value::{self, Value as Json};

use source::{Source, SourceError};

#[derive(Clone)]
pub struct Template {
    name: Option<String>,
    content: Option<String>,
    value: Json,
}

#[cfg(not(feature = "serde_type"))]
impl Template {
    /// render some template from pre-registered templates
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: Some(name.to_string()),
            value: value.to_json(),
            content: None,
        }
    }

    /// render some template with temporary template string
    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value.to_json(),
            content: Some(content.to_string()),
        }
    }
}

#[cfg(feature = "serde_type")]
impl Template {
    /// render some template from pre-registered templates
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: Some(name.to_string()),
            value: value::to_value(&value),
            content: None,
        }
    }

    /// render some template with temporary template string
    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value::to_value(&value),
            content: Some(content.to_string()),
        }
    }
}

pub struct HandlebarsEngine {
    pub sources: Vec<Box<Source + Send + Sync>>,
    pub registry: RwLock<Box<Handlebars>>,
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl PluginFor<Response> for HandlebarsEngine {
    type Error = ();

    fn eval(resp: &mut Response) -> Result<Template, ()> {
        match resp.extensions.get::<HandlebarsEngine>() {
            Some(t) => Ok(t.clone()),
            None => Err(()),
        }
    }
}

impl HandlebarsEngine {
    pub fn new() -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(Handlebars::new())),
        }
    }

    pub fn from(reg: Handlebars) -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(reg)),
        }
    }

    pub fn add(&mut self, source: Box<Source + Send + Sync>) {
        self.sources.push(source);
    }

    pub fn reload(&self) -> Result<(), SourceError> {
        let mut hbs = self.handlebars_mut();
        hbs.clear_templates();
        for s in self.sources.iter() {
            try!(s.load(&mut hbs))
        }
        Ok(())
    }

    pub fn handlebars_mut(&self) -> RwLockWriteGuard<Box<Handlebars>> {
        self.registry.write().unwrap()
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, mut resp: Response) -> IronResult<Response> {
        let page_wrapper = resp.extensions
                               .remove::<HandlebarsEngine>()
                               .and_then(|h| {
                                   let hbs = self.registry.read().unwrap();
                                   if let Some(ref name) = h.name {
                                       return Some(hbs.render(name, &h.value)
                                                      .map_err(TemplateRenderError::from));
                                   } else if let Some(ref content) = h.content {
                                       return Some(hbs.template_render(content, &h.value));
                                   } else {
                                       unreachable!();
                                   }
                               });

        match page_wrapper {
            Some(page_result) => {
                match page_result {
                    Ok(page) => {
                        if !resp.headers.has::<ContentType>() {
                            resp.headers.set(ContentType::html());
                        }
                        resp.set_mut(page);
                        Ok(resp)
                    }
                    Err(e) => {
                        info!("{}", e.description());
                        Err(IronError::new(e, status::InternalServerError))
                    }
                }
            }
            None => Ok(resp),
        }
    }

    fn catch(&self, req: &mut Request, mut err: IronError) -> IronResult<Response> {
        err.response = try!(self.after(req, err.response));
        Err(err)
    }
}

#[cfg(test)]
mod test {
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;
    use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::new("index", data)))
    }

    fn hello_world2() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::with("{{title}}", data)))
    }

    #[test]
    #[cfg(not(feature = "serde_type"))]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name.unwrap(), "index".to_string());
                assert_eq!(h.value
                            .as_object()
                            .unwrap()
                            .get(&"title".to_string())
                            .unwrap()
                            .as_string()
                            .unwrap(),
                           "Handlebars on Iron");
            }
            _ => panic!("template expected"),
        }
    }

    #[test]
    #[cfg(feature = "serde_type")]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name.unwrap(), "index".to_string());
                assert_eq!(h.value
                            .as_object()
                            .unwrap()
                            .get(&"title".to_string())
                            .unwrap()
                            .as_str()
                            .unwrap(),
                           "Handlebars on Iron");
            }
            _ => panic!("template expected"),
        }
    }

    #[test]
    #[cfg(not(feature = "serde_type"))]
    fn test_resp_set2() {
        let mut resp = hello_world2().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.content.unwrap(), "{{title}}".to_string());
                assert_eq!(h.value
                            .as_object()
                            .unwrap()
                            .get(&"title".to_string())
                            .unwrap()
                            .as_string()
                            .unwrap(),
                           "Handlebars on Iron");
            }
            _ => panic!("template expected"),
        }
    }

    #[test]
    #[cfg(feature = "serde_type")]
    fn test_resp_set2() {
        let mut resp = hello_world2().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.content.unwrap(), "{{title}}".to_string());
                assert_eq!(h.value
                            .as_object()
                            .unwrap()
                            .get(&"title".to_string())
                            .unwrap()
                            .as_str()
                            .unwrap(),
                           "Handlebars on Iron");
            }
            _ => panic!("template expected"),
        }
    }

    #[test]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new();
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore",
                            Box::new(|_: &Context,
                                      _: &Helper,
                                      _: &Handlebars,
                                      _: &mut RenderContext|
                                      -> Result<(), RenderError> {
                                Ok(())
                            }));
    }
}
<commit_msg>(test) fix test in handlebars upgrade<commit_after>use std::sync::{RwLock, RwLockWriteGuard};
use std::error::Error;

use iron::prelude::*;
use iron::status;
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use plugin::Plugin as PluginFor;
use iron::headers::ContentType;

use handlebars::{Handlebars, TemplateRenderError};
#[cfg(not(feature = "serde_type"))]
use serialize::json::{ToJson, Json};
#[cfg(feature = "serde_type")]
use serde::ser::Serialize as ToJson;
#[cfg(feature = "serde_type")]
use serde_json::value::{self, Value as Json};

use source::{Source, SourceError};

#[derive(Clone)]
pub struct Template {
    name: Option<String>,
    content: Option<String>,
    value: Json,
}

#[cfg(not(feature = "serde_type"))]
impl Template {
    /// render some template from pre-registered templates
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: Some(name.to_string()),
            value: value.to_json(),
            content: None,
        }
    }

    /// render some template with temporary template string
    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value.to_json(),
            content: Some(content.to_string()),
        }
    }
}

#[cfg(feature = "serde_type")]
impl Template {
    /// render some template from pre-registered templates
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: Some(name.to_string()),
            value: value::to_value(&value),
            content: None,
        }
    }

    /// render some template with temporary template string
    pub fn with<T: ToJson>(content: &str, value: T) -> Template {
        Template {
            name: None,
            value: value::to_value(&value),
            content: Some(content.to_string()),
        }
    }
}

pub struct HandlebarsEngine {
    pub sources: Vec<Box<Source + Send + Sync>>,
    pub registry: RwLock<Box<Handlebars>>,
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl PluginFor<Response> for HandlebarsEngine {
    type Error = ();

    fn eval(resp: &mut Response) -> Result<Template, ()> {
        match resp.extensions.get::<HandlebarsEngine>() {
            Some(t) => Ok(t.clone()),
            None => Err(()),
        }
    }
}

impl HandlebarsEngine {
    pub fn new() -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(Handlebars::new())),
        }
    }

    pub fn from(reg: Handlebars) -> HandlebarsEngine {
        HandlebarsEngine {
            sources: Vec::new(),
            registry: RwLock::new(Box::new(reg)),
        }
    }

    pub fn add(&mut self, source: Box<Source + Send + Sync>) {
        self.sources.push(source);
    }

    pub fn reload(&self) -> Result<(), SourceError> {
        let mut hbs = self.handlebars_mut();
        hbs.clear_templates();
        for s in self.sources.iter() {
            try!(s.load(&mut hbs))
        }
        Ok(())
    }

    pub fn handlebars_mut(&self) -> RwLockWriteGuard<Box<Handlebars>> {
        self.registry.write().unwrap()
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, mut resp: Response) -> IronResult<Response> {
        let page_wrapper = resp.extensions
                               .remove::<HandlebarsEngine>()
                               .and_then(|h| {
                                   let hbs = self.registry.read().unwrap();
                                   if let Some(ref name) = h.name {
                                       return Some(hbs.render(name, &h.value)
                                                      .map_err(TemplateRenderError::from));
                                   } else if let Some(ref content) = h.content {
                                       return Some(hbs.template_render(content, &h.value));
                                   } else {
                                       unreachable!();
                                   }
                               });

        match page_wrapper {
            Some(page_result) => {
                match page_result {
                    Ok(page) => {
                        if !resp.headers.has::<ContentType>() {
                            resp.headers.set(ContentType::html());
                        }
                        resp.set_mut(page);
                        Ok(resp)
                    }
                    Err(e) => {
                        info!("{}", e.description());
                        Err(IronError::new(e, status::InternalServerError))
                    }
                }
            }
            None => Ok(resp),
        }
    }

    fn catch(&self, req: &mut Request, mut err: IronError) -> IronResult<Response> {
        err.response = try!(self.after(req, err.response));
        Err(err)
    }
}

#[cfg(test)]
mod test {
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;
    use handlebars::{Handlebars, RenderError, RenderContext, Helper};

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::new("index", data)))
    }

    fn hello_world2() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_owned(), "Handlebars on Iron".to_owned());

        Ok(resp.set(Template::with("{{title}}", data)))
    }

    #[test]
    #[cfg(not(feature = "serde_type"))]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name.unwrap(), "index".to_string());
                assert_eq!(h.value
                            .as_object()
                            .unwrap()
                            .get(&"title".to_string())
                            .unwrap()
                            .as_string()
                            .unwrap(),
                           "Handlebars on Iron");
            }
            _ => panic!("template expected"),
        }
    }

    #[test]
    #[cfg(feature = "serde_type")]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name.unwrap(), "index".to_string());
                assert_eq!(h.value
                            .as_object()
                            .unwrap()
                            .get(&"title".to_string())
                            .unwrap()
                            .as_str()
                            .unwrap(),
                           "Handlebars on Iron");
            }
            _ => panic!("template expected"),
        }
    }

    #[test]
    #[cfg(not(feature = "serde_type"))]
    fn test_resp_set2() {
        let mut resp = hello_world2().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.content.unwrap(), "{{title}}".to_string());
                assert_eq!(h.value
                            .as_object()
                            .unwrap()
                            .get(&"title".to_string())
                            .unwrap()
                            .as_string()
                            .unwrap(),
                           "Handlebars on Iron");
            }
            _ => panic!("template expected"),
        }
    }

    #[test]
    #[cfg(feature = "serde_type")]
    fn test_resp_set2() {
        let mut resp = hello_world2().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.content.unwrap(), "{{title}}".to_string());
                assert_eq!(h.value
                            .as_object()
                            .unwrap()
                            .get(&"title".to_string())
                            .unwrap()
                            .as_str()
                            .unwrap(),
                           "Handlebars on Iron");
            }
            _ => panic!("template expected"),
        }
    }

    #[test]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new();
        let mut reg = hbs.handlebars_mut();
        reg.register_helper("ignore",
                            Box::new(|_: &Helper,
                                      _: &Handlebars,
                                      _: &mut RenderContext|
                                      -> Result<(), RenderError> {
                                Ok(())
                            }));
    }
}
<|endoftext|>


<commit_before>extern crate sync;
extern crate nickel;
extern crate sqlite3;

use nickel::{Request, Middleware, Response, Action, NickelError, Continue};
use sqlite3::core::DatabaseConnection;
use sqlite3::access;
use self::sync::{Mutex, Arc};

#[deriving(Clone)]
pub struct Sqlite3Middleware
{
    conn: Arc<Mutex<DatabaseConnection>>
}

impl Sqlite3Middleware
{
    pub fn new(file: String) -> Sqlite3Middleware
    {
        Sqlite3Middleware
        {
            conn: Arc::new(Mutex::new(access::open(file).unwrap()))
        }
    }
}

impl Middleware for Sqlite3Middleware
{
    fn invoke(&self, req: &mut Request, _: &mut Response) -> Result<Action, NickelError>
    {
        req.map.insert(self.conn.clone());
        Ok(Continue)
    }
}

pub trait Sqlite3RequestExtensions
{
    fn db_conn(&self) -> &Arc<Mutex<DatabaseConnection>>;
}

impl<'a> Sqlite3RequestExtensions for Request<'a>
{
    fn db_conn(&self) -> &Arc<Mutex<DatabaseConnection>>
    {
        return self.map.find::<Arc<Mutex<DatabaseConnection>>>().unwrap()
    }
}
<commit_msg>Useful messages when failing.<commit_after>extern crate sync;
extern crate nickel;
extern crate sqlite3;

use nickel::{Request, Middleware, Response, Action, NickelError, Continue};
use sqlite3::core::DatabaseConnection;
use sqlite3::access;
use self::sync::{Mutex, Arc};

#[deriving(Clone)]
pub struct Sqlite3Middleware
{
    conn: Arc<Mutex<DatabaseConnection>>
}

impl Sqlite3Middleware
{
    pub fn new(file: String) -> Sqlite3Middleware
    {
        Sqlite3Middleware
        {
            conn: Arc::new(Mutex::new(match access::open(file)
                                        {
                                          Ok(f) => f,
                                          Err(e) => fail!("Couldn't open db: {}", e),
                                        }
                                     ))
        }
    }
}

impl Middleware for Sqlite3Middleware
{
    fn invoke(&self, req: &mut Request, _: &mut Response) -> Result<Action, NickelError>
    {
        req.map.insert(self.conn.clone());
        Ok(Continue)
    }
}

pub trait Sqlite3RequestExtensions
{
    fn db_conn(&self) -> &Arc<Mutex<DatabaseConnection>>;
}

impl<'a> Sqlite3RequestExtensions for Request<'a>
{
    fn db_conn(&self) -> &Arc<Mutex<DatabaseConnection>>
    {
        return match self.map.find::<Arc<Mutex<DatabaseConnection>>>()
        {
            Some(db) => db,
            None => fail!("Couldn't find DB connection."),
        }
    }
}
<|endoftext|>


<commit_before>//! Provides an oscillator that generates periodic waveforms.

use std::f32::consts::PI;
use num::traits::Float;
use rand::random;

use types::{SAMPLE_RATE, AudioDevice, Sample, Time};

/// Defines the messages that the Oscillator supports
#[derive(Clone, Copy, Debug)]
pub enum OscillatorMessage {
    /// Sets the frequency in Hz
    SetFreq(f32),
    /// Sets the waveform type
    SetWaveform(Waveform),
    /// Sets the LFO vibrato depth, in steps
    SetLFOIntensity(f32),
    /// Sets the pitch bend, in steps
    SetBend(f32),
}
pub use self::OscillatorMessage::*;

/// Antialiasing method for certain waveforms.
///
/// Aliased waveforms will use naive methods that produce aliasing.
/// PolyBLEP (Polynomial Bandlimited Step) uses offsets to round off sharp edges
/// and reduce aliasing.
#[derive(Clone, Copy, Debug)]
pub enum AntialiasType {
    /// Naive, aliasing waveforms.
    Aliased,
    /// Antialiasing using PolyBLEP.
    PolyBlep
}
pub use self::AntialiasType::*;

/// Oscillator waveforms.
///
/// `Saw`, `Square`, and `Tri` provides either aliased waveforms, or antialiased
/// waveforms using PolyBLEP. Aliased waveformsare useful for control signals,
/// but not for raw audio signals. For audible signals, instead used the
/// corresponding `PolyBlep` waveforms.
#[derive(Clone, Copy, Debug)]
pub enum Waveform {
    Sine,
    Saw(AntialiasType),
    Square(AntialiasType),
    Tri(AntialiasType),
    WhiteNoise,
    PulseTrain
}
pub use self::Waveform::*;

/// An oscillator that generates a periodic waveform.
pub struct Oscillator {
    waveform: Waveform,
    lfo_intensity: f32,
    bend: f32,
    phase: f32,
    phase_delta: f32,
    last_sample: Sample,
}

impl Oscillator {
    /// Returns an oscillator with the specified waveform at the specified
    /// frequency, in Hz.
    pub fn new(waveform: Waveform) -> Oscillator {
        Oscillator {
            waveform: waveform,
            lfo_intensity: 0.0,
            bend: 1.0,
            phase: 0.0,
            phase_delta: 0.0,
            last_sample: 0.0
        }
    }

    pub fn freq(mut self, freq: f32) -> Oscillator {
        self.handle_message(SetFreq(freq));
        self
    }

    pub fn lfo_intensity(mut self, lfo_intensity: f32) -> Oscillator {
        self.handle_message(SetLFOIntensity(lfo_intensity));
        self
    }

    /// Applies the message to the oscillator
    pub fn handle_message(&mut self, msg: OscillatorMessage) {
        match msg {
            SetFreq(freq) => {
                self.phase_delta = freq*2.0*PI/(SAMPLE_RATE as f32);
            },
            SetWaveform(waveform) => {
                self.waveform = waveform;
            },
            SetLFOIntensity(steps) => {
                self.lfo_intensity = steps/12.0;
            },
            SetBend(steps) => {
                self.bend = 2.0.powf(steps/12.0);
            },
        }
    }
}

impl AudioDevice for Oscillator {
    fn num_inputs(&self) -> usize {
        1
    }

    fn num_outputs(&self) -> usize {
        1
    }

    fn tick(&mut self, _: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        // Tick the phase
        let phase_delta = if inputs.len() > 0 {
            self.phase_delta*2.0.powf(inputs[0]*self.lfo_intensity)*self.bend
        } else {
            self.phase_delta*self.bend
        };
        self.phase += phase_delta;
        if self.phase >= 2.0*PI {
            self.phase -= 2.0*PI;
        }

        // Compute the next sample
        let s: Sample = match self.waveform.clone() {
            Sine => self.phase.sin(),
            Saw(aa) => {
                let mut out = self.phase/PI -1.0;
                match aa {
                    PolyBlep => {
                        out -= poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Square(aa) => {
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(fmod(self.phase/(2.0*PI)+0.5, 1.0),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Tri(aa) => {
                // Compute a square wave signal
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(fmod(self.phase/(2.0*PI)+0.5, 1.0),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }

                // Perform leaky integration
                phase_delta*out + (1.0-phase_delta)*self.last_sample
            },
            WhiteNoise => 2.0*random::<f32>() - 1.0,
            PulseTrain => {
                // If we wrapped around...
                if self.phase < self.phase_delta {
                    1.0
                } else {
                    0.0
                }
            }
        };

        // Push the sample out
        self.last_sample = s;
        outputs[0] = s;
    }
}

/// Floating point modulus
fn fmod(n: f32, base: f32) -> f32 {
    assert!(base > 0.0);
    let mut out = n;
    while out < 0.0 {
        out += base;
    }
    while out >= base {
        out -= base;
    }
    out
}

/// Computes an offset for PolyBLEP antialiasing
///
/// `t` should be the current waveform phase, normalized
/// `dt` should be the change in phase for one sample time, normalized
fn poly_belp_offset(t: f32, dt: f32) -> f32 {
    if t < dt { // t ~= 0
        let t = t / dt;
        -t*t + 2.0*t - 1.0
    } else if t > 1.0-dt { // t ~= 1
        let t = (t-1.0) / dt;
        t*t + 2.0*t + 1.0
    } else {
        0.0
    }
}

// A couple of basic unit tests...
#[cfg(test)]
mod test {
    use utils::helpers::flt_eq;
    static EPSILON: f32 = 1e-6;

    /// Tests fmod with many values
    #[test]
    fn test_fmod() {
        use super::fmod;

        // negatives...
        assert!(flt_eq(fmod(-1.5, 1.0), 0.5, EPSILON));
        assert!(flt_eq(fmod(-1.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(-0.5, 1.0), 0.5, EPSILON));

        // in range...
        assert!(flt_eq(fmod(0.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(0.5, 1.0), 0.5, EPSILON));
        assert!(flt_eq(fmod(0.9, 1.0), 0.9, EPSILON));

        // above...
        assert!(flt_eq(fmod(1.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(1.5, 1.0), 0.5, EPSILON));
        assert!(flt_eq(fmod(2.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(2.5, 1.0), 0.5, EPSILON));

        // different base...
        assert!(flt_eq(fmod(-0.5, 0.9), 0.4, EPSILON));
        assert!(flt_eq(fmod(0.0, 0.9), 0.0, EPSILON));
        assert!(flt_eq(fmod(0.5, 0.9), 0.5, EPSILON));
        assert!(flt_eq(fmod(0.9, 0.9), 0.0, EPSILON));
        assert!(flt_eq(fmod(1.0, 0.9), 0.1, EPSILON));
    }

    /// Tests square wave
    #[test]
    fn test_naive_square() {
        use super::{AntialiasType, Waveform, Oscillator};
        use types::AudioDevice;
        let mut osc = Oscillator::new(Waveform::Square(AntialiasType::Aliased),
                                      4410.0);
        let input = vec![];
        let mut output = vec![0.0];

        osc.tick(0, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(1, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(2, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(3, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(4, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(5, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(6, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(7, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(8, &input, &mut output); assert!(output[0] == -1.0);
    }

    /// Tests saw wave
    #[test]
    fn test_naive_saw() {
        use super::{AntialiasType, Waveform, Oscillator};
        use types::AudioDevice;
        let mut osc = Oscillator::new(Waveform::Saw(AntialiasType::Aliased),
                                      4410.0);
        let input = vec![];
        let mut output = vec![0.0];

        osc.tick(0, &input, &mut output); assert!(flt_eq(output[0], -0.8, EPSILON));
        osc.tick(1, &input, &mut output); assert!(flt_eq(output[0], -0.6, EPSILON));
        osc.tick(2, &input, &mut output); assert!(flt_eq(output[0], -0.4, EPSILON));
        osc.tick(3, &input, &mut output); assert!(flt_eq(output[0], -0.2, EPSILON));
        osc.tick(4, &input, &mut output); assert!(flt_eq(output[0], 0.0, EPSILON));
        osc.tick(5, &input, &mut output); assert!(flt_eq(output[0], 0.2, EPSILON));
        osc.tick(6, &input, &mut output); assert!(flt_eq(output[0], 0.4, EPSILON));
        osc.tick(7, &input, &mut output); assert!(flt_eq(output[0], 0.6, EPSILON));
        osc.tick(8, &input, &mut output); assert!(flt_eq(output[0], 0.8, EPSILON));
    }
}
<commit_msg>Update oscillator tests to use builder interface<commit_after>//! Provides an oscillator that generates periodic waveforms.

use std::f32::consts::PI;
use num::traits::Float;
use rand::random;

use types::{SAMPLE_RATE, AudioDevice, Sample, Time};

/// Defines the messages that the Oscillator supports
#[derive(Clone, Copy, Debug)]
pub enum OscillatorMessage {
    /// Sets the frequency in Hz
    SetFreq(f32),
    /// Sets the waveform type
    SetWaveform(Waveform),
    /// Sets the LFO vibrato depth, in steps
    SetLFOIntensity(f32),
    /// Sets the pitch bend, in steps
    SetBend(f32),
}
pub use self::OscillatorMessage::*;

/// Antialiasing method for certain waveforms.
///
/// Aliased waveforms will use naive methods that produce aliasing.
/// PolyBLEP (Polynomial Bandlimited Step) uses offsets to round off sharp edges
/// and reduce aliasing.
#[derive(Clone, Copy, Debug)]
pub enum AntialiasType {
    /// Naive, aliasing waveforms.
    Aliased,
    /// Antialiasing using PolyBLEP.
    PolyBlep
}
pub use self::AntialiasType::*;

/// Oscillator waveforms.
///
/// `Saw`, `Square`, and `Tri` provides either aliased waveforms, or antialiased
/// waveforms using PolyBLEP. Aliased waveformsare useful for control signals,
/// but not for raw audio signals. For audible signals, instead used the
/// corresponding `PolyBlep` waveforms.
#[derive(Clone, Copy, Debug)]
pub enum Waveform {
    Sine,
    Saw(AntialiasType),
    Square(AntialiasType),
    Tri(AntialiasType),
    WhiteNoise,
    PulseTrain
}
pub use self::Waveform::*;

/// An oscillator that generates a periodic waveform.
pub struct Oscillator {
    waveform: Waveform,
    lfo_intensity: f32,
    bend: f32,
    phase: f32,
    phase_delta: f32,
    last_sample: Sample,
}

impl Oscillator {
    /// Returns an oscillator with the specified waveform at the specified
    /// frequency, in Hz.
    pub fn new(waveform: Waveform) -> Oscillator {
        Oscillator {
            waveform: waveform,
            lfo_intensity: 0.0,
            bend: 1.0,
            phase: 0.0,
            phase_delta: 0.0,
            last_sample: 0.0
        }
    }

    pub fn freq(mut self, freq: f32) -> Oscillator {
        self.handle_message(SetFreq(freq));
        self
    }

    pub fn lfo_intensity(mut self, lfo_intensity: f32) -> Oscillator {
        self.handle_message(SetLFOIntensity(lfo_intensity));
        self
    }

    /// Applies the message to the oscillator
    pub fn handle_message(&mut self, msg: OscillatorMessage) {
        match msg {
            SetFreq(freq) => {
                self.phase_delta = freq*2.0*PI/(SAMPLE_RATE as f32);
            },
            SetWaveform(waveform) => {
                self.waveform = waveform;
            },
            SetLFOIntensity(steps) => {
                self.lfo_intensity = steps/12.0;
            },
            SetBend(steps) => {
                self.bend = 2.0.powf(steps/12.0);
            },
        }
    }
}

impl AudioDevice for Oscillator {
    fn num_inputs(&self) -> usize {
        1
    }

    fn num_outputs(&self) -> usize {
        1
    }

    fn tick(&mut self, _: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        // Tick the phase
        let phase_delta = if inputs.len() > 0 {
            self.phase_delta*2.0.powf(inputs[0]*self.lfo_intensity)*self.bend
        } else {
            self.phase_delta*self.bend
        };
        self.phase += phase_delta;
        if self.phase >= 2.0*PI {
            self.phase -= 2.0*PI;
        }

        // Compute the next sample
        let s: Sample = match self.waveform.clone() {
            Sine => self.phase.sin(),
            Saw(aa) => {
                let mut out = self.phase/PI -1.0;
                match aa {
                    PolyBlep => {
                        out -= poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Square(aa) => {
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(fmod(self.phase/(2.0*PI)+0.5, 1.0),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Tri(aa) => {
                // Compute a square wave signal
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(fmod(self.phase/(2.0*PI)+0.5, 1.0),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }

                // Perform leaky integration
                phase_delta*out + (1.0-phase_delta)*self.last_sample
            },
            WhiteNoise => 2.0*random::<f32>() - 1.0,
            PulseTrain => {
                // If we wrapped around...
                if self.phase < self.phase_delta {
                    1.0
                } else {
                    0.0
                }
            }
        };

        // Push the sample out
        self.last_sample = s;
        outputs[0] = s;
    }
}

/// Floating point modulus
fn fmod(n: f32, base: f32) -> f32 {
    assert!(base > 0.0);
    let mut out = n;
    while out < 0.0 {
        out += base;
    }
    while out >= base {
        out -= base;
    }
    out
}

/// Computes an offset for PolyBLEP antialiasing
///
/// `t` should be the current waveform phase, normalized
/// `dt` should be the change in phase for one sample time, normalized
fn poly_belp_offset(t: f32, dt: f32) -> f32 {
    if t < dt { // t ~= 0
        let t = t / dt;
        -t*t + 2.0*t - 1.0
    } else if t > 1.0-dt { // t ~= 1
        let t = (t-1.0) / dt;
        t*t + 2.0*t + 1.0
    } else {
        0.0
    }
}

// A couple of basic unit tests...
#[cfg(test)]
mod test {
    use utils::helpers::flt_eq;
    static EPSILON: f32 = 1e-6;

    /// Tests fmod with many values
    #[test]
    fn test_fmod() {
        use super::fmod;

        // negatives...
        assert!(flt_eq(fmod(-1.5, 1.0), 0.5, EPSILON));
        assert!(flt_eq(fmod(-1.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(-0.5, 1.0), 0.5, EPSILON));

        // in range...
        assert!(flt_eq(fmod(0.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(0.5, 1.0), 0.5, EPSILON));
        assert!(flt_eq(fmod(0.9, 1.0), 0.9, EPSILON));

        // above...
        assert!(flt_eq(fmod(1.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(1.5, 1.0), 0.5, EPSILON));
        assert!(flt_eq(fmod(2.0, 1.0), 0.0, EPSILON));
        assert!(flt_eq(fmod(2.5, 1.0), 0.5, EPSILON));

        // different base...
        assert!(flt_eq(fmod(-0.5, 0.9), 0.4, EPSILON));
        assert!(flt_eq(fmod(0.0, 0.9), 0.0, EPSILON));
        assert!(flt_eq(fmod(0.5, 0.9), 0.5, EPSILON));
        assert!(flt_eq(fmod(0.9, 0.9), 0.0, EPSILON));
        assert!(flt_eq(fmod(1.0, 0.9), 0.1, EPSILON));
    }

    /// Tests square wave
    #[test]
    fn test_naive_square() {
        use super::{AntialiasType, Waveform, Oscillator};
        use types::AudioDevice;
        let mut osc = Oscillator::new(Waveform::Square(AntialiasType::Aliased))
            .freq(4410.0);
        let input = vec![];
        let mut output = vec![0.0];

        osc.tick(0, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(1, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(2, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(3, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(4, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(5, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(6, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(7, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(8, &input, &mut output); assert!(output[0] == -1.0);
    }

    /// Tests saw wave
    #[test]
    fn test_naive_saw() {
        use super::{AntialiasType, Waveform, Oscillator};
        use types::AudioDevice;
        let mut osc = Oscillator::new(Waveform::Saw(AntialiasType::Aliased))
            .freq(4410.0);
        let input = vec![];
        let mut output = vec![0.0];

        osc.tick(0, &input, &mut output); assert!(flt_eq(output[0], -0.8, EPSILON));
        osc.tick(1, &input, &mut output); assert!(flt_eq(output[0], -0.6, EPSILON));
        osc.tick(2, &input, &mut output); assert!(flt_eq(output[0], -0.4, EPSILON));
        osc.tick(3, &input, &mut output); assert!(flt_eq(output[0], -0.2, EPSILON));
        osc.tick(4, &input, &mut output); assert!(flt_eq(output[0], 0.0, EPSILON));
        osc.tick(5, &input, &mut output); assert!(flt_eq(output[0], 0.2, EPSILON));
        osc.tick(6, &input, &mut output); assert!(flt_eq(output[0], 0.4, EPSILON));
        osc.tick(7, &input, &mut output); assert!(flt_eq(output[0], 0.6, EPSILON));
        osc.tick(8, &input, &mut output); assert!(flt_eq(output[0], 0.8, EPSILON));
    }
}
<|endoftext|>


<commit_before>//! Wrapper around `PropertyParser`
//!
//! #### Warning
//!   The parsers (`VcardParser` / `IcalParser`) only parse the content and set to uppercase
//!   the case-insensitive fields.  No checks are made on the fields validity.
//!
//!

pub mod ical;
pub mod vcard;

// Sys mods
use std::cell::RefCell;
use std::io::BufRead;

// Internal mods
use crate::property::{Property, PropertyError, PropertyParser};

#[derive(Debug, Error)]
pub enum ParserError {
    #[error("invalid component")]
    InvalidComponent,
    #[error("incomplete object")]
    NotComplete,
    #[error("missing header")]
    MissingHeader,
    #[error("property error")]
    PropertyError(#[from] PropertyError),
}

/// An interface for an Ical/Vcard component.
///
/// It take a `PropertyParser` and fill the component with. It's also able to create
/// sub-component used by event and alarms.
pub trait Component {
    /// Add the givent sub component.
    fn add_sub_component<B: BufRead>(
        &mut self,
        value: &str,
        line_parser: &RefCell<PropertyParser<B>>,
    ) -> Result<(), ParserError>;

    /// Add the givent property.
    fn add_property(&mut self, property: Property);

    /// Parse the content from `line_parser` and fill the component with.
    fn parse<B: BufRead>(
        &mut self,
        line_parser: &RefCell<PropertyParser<B>>,
    ) -> Result<(), ParserError> {
        loop {
            let line: Property;

            {
                line = match line_parser.borrow_mut().next() {
                    Some(val) => val.map_err(|e| ParserError::PropertyError(e))?,
                    None => return Err(ParserError::NotComplete.into()),
                };
            }

            match line.name.to_uppercase().as_str() {
                "END" => break,
                "BEGIN" => match line.value {
                    Some(v) => self.add_sub_component(v.as_str(), line_parser)?,
                    None => return Err(ParserError::NotComplete.into()),
                },

                _ => self.add_property(line),
            };
        }

        Ok(())
    }
}
<commit_msg>Show detailed property error message<commit_after>//! Wrapper around `PropertyParser`
//!
//! #### Warning
//!   The parsers (`VcardParser` / `IcalParser`) only parse the content and set to uppercase
//!   the case-insensitive fields.  No checks are made on the fields validity.
//!
//!

pub mod ical;
pub mod vcard;

// Sys mods
use std::cell::RefCell;
use std::io::BufRead;

// Internal mods
use crate::property::{Property, PropertyError, PropertyParser};

#[derive(Debug, Error)]
pub enum ParserError {
    #[error("invalid component")]
    InvalidComponent,
    #[error("incomplete object")]
    NotComplete,
    #[error("missing header")]
    MissingHeader,
    #[error("property error: {0}")]
    PropertyError(#[from] PropertyError),
}

/// An interface for an Ical/Vcard component.
///
/// It take a `PropertyParser` and fill the component with. It's also able to create
/// sub-component used by event and alarms.
pub trait Component {
    /// Add the givent sub component.
    fn add_sub_component<B: BufRead>(
        &mut self,
        value: &str,
        line_parser: &RefCell<PropertyParser<B>>,
    ) -> Result<(), ParserError>;

    /// Add the givent property.
    fn add_property(&mut self, property: Property);

    /// Parse the content from `line_parser` and fill the component with.
    fn parse<B: BufRead>(
        &mut self,
        line_parser: &RefCell<PropertyParser<B>>,
    ) -> Result<(), ParserError> {
        loop {
            let line: Property;

            {
                line = match line_parser.borrow_mut().next() {
                    Some(val) => val.map_err(|e| ParserError::PropertyError(e))?,
                    None => return Err(ParserError::NotComplete.into()),
                };
            }

            match line.name.to_uppercase().as_str() {
                "END" => break,
                "BEGIN" => match line.value {
                    Some(v) => self.add_sub_component(v.as_str(), line_parser)?,
                    None => return Err(ParserError::NotComplete.into()),
                },

                _ => self.add_property(line),
            };
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>#[cfg_attr(rustfmt, rustfmt_skip)]
mod grammar;

/// Contains all structures related to the AST for the WebIDL grammar.
pub mod ast;

use lalrpop_util::ParseError;

use lexer::{LexicalError, Token};

/// The result that is returned when an input string is parsed. If the parse succeeds, the `Ok`
/// result will be a vector of definitions representing the AST. If the parse fails, the `Err` will
/// be either an error from the lexer or the parser.
pub type ParseResult = Result<Vec<ast::Definition>, ParseError<usize, Token, LexicalError>>;

/// The parser that is used to parse WebIDL. It really serves as a wrapper around the parse
/// function exposed by lalrpop.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Parser;

impl Parser {
    /// Parses a given input string and returns an AST.
    ///
    /// # Example
    ///
    /// ```
    /// use webidl_parser::*;
    /// use webidl_parser::ast::*;
    ///
    /// let result = Parser::parse_string("[Attribute] interface Node { };");
    ///
    /// assert_eq!(result,
    ///            Ok(vec![Definition {
    ///                 definition_type: DefinitionType::Interface(Interface {
    ///                     members: vec![],
    ///                     name: "Node".to_string(),
    ///                     type_:
    ///                         InterfaceType::NonPartial(None),
    ///                 }),
    ///                 extended_attributes: vec![
    ///                     Box::new(ExtendedAttribute::Other {
    ///                         other: Other::Identifier("Attribute".to_string()),
    ///                         rest: None,
    ///                     })],
    ///            }]));
    ///
    /// ```
    pub fn parse_string(input: &str) -> ParseResult {
        grammar::parse_Definitions(::Lexer::new(input))
    }
}
<commit_msg>disable clippy on generated grammar file<commit_after>#[cfg_attr(rustfmt, rustfmt_skip)]
#[allow(clippy)]
#[allow(unknown_lints)]
mod grammar;

/// Contains all structures related to the AST for the WebIDL grammar.
pub mod ast;

use lalrpop_util::ParseError;

use lexer::{LexicalError, Token};

/// The result that is returned when an input string is parsed. If the parse succeeds, the `Ok`
/// result will be a vector of definitions representing the AST. If the parse fails, the `Err` will
/// be either an error from the lexer or the parser.
pub type ParseResult = Result<Vec<ast::Definition>, ParseError<usize, Token, LexicalError>>;

/// The parser that is used to parse WebIDL. It really serves as a wrapper around the parse
/// function exposed by lalrpop.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Parser;

impl Parser {
    /// Parses a given input string and returns an AST.
    ///
    /// # Example
    ///
    /// ```
    /// use webidl_parser::*;
    /// use webidl_parser::ast::*;
    ///
    /// let result = Parser::parse_string("[Attribute] interface Node { };");
    ///
    /// assert_eq!(result,
    ///            Ok(vec![Definition {
    ///                 definition_type: DefinitionType::Interface(Interface {
    ///                     members: vec![],
    ///                     name: "Node".to_string(),
    ///                     type_:
    ///                         InterfaceType::NonPartial(None),
    ///                 }),
    ///                 extended_attributes: vec![
    ///                     Box::new(ExtendedAttribute::Other {
    ///                         other: Other::Identifier("Attribute".to_string()),
    ///                         rest: None,
    ///                     })],
    ///            }]));
    ///
    /// ```
    pub fn parse_string(input: &str) -> ParseResult {
        grammar::parse_Definitions(::Lexer::new(input))
    }
}
<|endoftext|>


<commit_before>#![feature(globs)]
#![feature(phase)]
#![feature(unboxed_closures)]
#![feature(macro_rules)]

extern crate regex;

pub mod parsers;

#[macro_escape]
pub mod macros;

mod tests;

mod peruse {
    pub use parsers;
}

<commit_msg>Update crate/module attributes for newer Rust<commit_after>#![feature(unboxed_closures)]

extern crate regex;

pub mod parsers;

#[macro_use]
pub mod macros;

mod tests;

mod peruse {
    pub use parsers;
}

<|endoftext|>


<commit_before>extern crate serial;

use std::env;
use std::thread;
use std::time::Duration;

use serial::prelude::*;

const SETTINGS: serial::PortSettings = serial::PortSettings {
    baud_rate:    serial::Baud9600,
    char_size:    serial::Bits8,
    parity:       serial::ParityNone,
    stop_bits:    serial::Stop1,
    flow_control: serial::FlowNone
};

fn main() {
    for arg in env::args_os().skip(1) {
        let mut port = serial::open(&arg).unwrap();
        println!("opened device {:?}", arg);
        probe_pins(&mut port).unwrap();
    }
}

fn probe_pins<T: SerialPort>(port: &mut T) -> serial::Result<()> {
    try!(port.configure(&SETTINGS));
    try!(port.set_timeout(Duration::from_millis(100)));

    try!(port.set_rts(false));
    try!(port.set_dtr(false));

    let mut rts = false;
    let mut dtr = false;
    let mut toggle = true;

    loop {
        thread::sleep_ms(1000);

        if toggle {
            rts = !rts;
            try!(port.set_rts(rts));
        }
        else {
            dtr = !dtr;
            try!(port.set_dtr(dtr));
        }

        println!("RTS={:5?} DTR={:5?} CTS={:5?} DSR={:5?} RI={:5?} CD={:?}",
                 rts,
                 dtr,
                 try!(port.read_cts()),
                 try!(port.read_dsr()),
                 try!(port.read_ri()),
                 try!(port.read_cd()));

        toggle = !toggle;
    }
}
<commit_msg>replaces use of deprecated std::thread::sleep_ms()<commit_after>extern crate serial;

use std::env;
use std::thread;
use std::time::Duration;

use serial::prelude::*;

const SETTINGS: serial::PortSettings = serial::PortSettings {
    baud_rate:    serial::Baud9600,
    char_size:    serial::Bits8,
    parity:       serial::ParityNone,
    stop_bits:    serial::Stop1,
    flow_control: serial::FlowNone
};

fn main() {
    for arg in env::args_os().skip(1) {
        let mut port = serial::open(&arg).unwrap();
        println!("opened device {:?}", arg);
        probe_pins(&mut port).unwrap();
    }
}

fn probe_pins<T: SerialPort>(port: &mut T) -> serial::Result<()> {
    try!(port.configure(&SETTINGS));
    try!(port.set_timeout(Duration::from_millis(100)));

    try!(port.set_rts(false));
    try!(port.set_dtr(false));

    let mut rts = false;
    let mut dtr = false;
    let mut toggle = true;

    loop {
        thread::sleep(Duration::from_secs(1));

        if toggle {
            rts = !rts;
            try!(port.set_rts(rts));
        }
        else {
            dtr = !dtr;
            try!(port.set_dtr(dtr));
        }

        println!("RTS={:5?} DTR={:5?} CTS={:5?} DSR={:5?} RI={:5?} CD={:?}",
                 rts,
                 dtr,
                 try!(port.read_cts()),
                 try!(port.read_dsr()),
                 try!(port.read_ri()),
                 try!(port.read_cd()));

        toggle = !toggle;
    }
}
<|endoftext|>


<commit_before>extern crate httpd = "tiny-http";

fn get_content_type(path: &Path) -> &'static str {
    let extension = match path.extension_str() {
        None => return "text/plain",
        Some(e) => e
    };

    match extension {
        "gif" => "image/gif",
        "jpg" => "image/jpeg",
        "jpeg" => "image/jpeg",
        "png" => "image/png",
        "pdf" => "application/pdf",
        "htm" => "text/html",
        "html" => "text/html",
        _ => "text/plain"
    }
}

fn main() {
    let (server, port) = httpd::Server::new_with_random_port().unwrap();
    println!("Now listening on port {}", port);

    loop {
        let rq = match server.recv() {
            Ok(rq) => rq,
            Err(_) => break
        };

        println!("{}", rq);

        let path = Path::new(rq.get_url().path.clone());
        let file = std::io::File::open(&path);

        if file.is_ok() {
            let response = httpd::Response::from_file(file.unwrap());

            let response = response.with_header(
                httpd::Header{
                    field: from_str("Content-Type").unwrap(),
                    value: get_content_type(&path).to_string()
                }
            );

            rq.respond(response);

        } else {
            let rep = httpd::Response::new_empty(httpd::StatusCode(404));
            rq.respond(rep);
        }
    }
}
<commit_msg>Fix charsets in serve-root example<commit_after>extern crate httpd = "tiny-http";

fn get_content_type(path: &Path) -> &'static str {
    let extension = match path.extension_str() {
        None => return "text/plain",
        Some(e) => e
    };

    match extension {
        "gif" => "image/gif",
        "jpg" => "image/jpeg",
        "jpeg" => "image/jpeg",
        "png" => "image/png",
        "pdf" => "application/pdf",
        "htm" => "text/html; charset=utf8",
        "html" => "text/html; charset=utf8",
        "txt" => "text/plain; charset=utf8",
        _ => "text/plain; charset=utf8"
    }
}

fn main() {
    let (server, port) = httpd::Server::new_with_random_port().unwrap();
    println!("Now listening on port {}", port);

    loop {
        let rq = match server.recv() {
            Ok(rq) => rq,
            Err(_) => break
        };

        println!("{}", rq);

        let path = Path::new(rq.get_url().path.clone());
        let file = std::io::File::open(&path);

        if file.is_ok() {
            let response = httpd::Response::from_file(file.unwrap());

            let response = response.with_header(
                httpd::Header{
                    field: from_str("Content-Type").unwrap(),
                    value: get_content_type(&path).to_string()
                }
            );

            rq.respond(response);

        } else {
            let rep = httpd::Response::new_empty(httpd::StatusCode(404));
            rq.respond(rep);
        }
    }
}
<|endoftext|>


<commit_before>//! Contatins code relating to the engine's scripting capability.

#[cfg(test)]
mod test;

use std::collections::HashMap;
use std::fmt::{Debug, Formatter};
use std::fmt;

use hlua::{Lua, PushGuard};
use hlua::lua_tables::LuaTable;

/// The engine lua standard library. Contains functionality relating to making a game with the engine.
///
/// Exposed as the module "buildstation" to lua code.
const ENGINE_STD: &'static str = include_str!("enginestd.lua");

/// A piece of code run before the main script.
const PRELUDE: &'static str = include_str!("prelude.lua");

/// Handles the scripts, their state, and their execution.
pub struct Engine<'lua> {
    /// The interpreter used for the scripts.
    pub interpreter: Lua<'lua>,
}

impl<'lua> Engine<'lua> {
    /// Constructs a script::Engine and loads the given scripts.
    ///
    /// The interpreter is initalized with the lua standard library, and the engine std.
    ///
    /// All scripts are loaded into the same namespace, and must return nothing when loaded.
    pub fn new(mut scripts: HashMap<String, String>) -> Self {
        scripts.insert("buildengine".to_owned(), ENGINE_STD.to_owned());
        let mut lua = Lua::new();
        lua.openlibs();
        lua.execute::<()>(PRELUDE).expect("Syntax error in prelude module of engine");
        let mut main = "".to_owned();
        {
            let mut prelude_table: LuaTable<PushGuard<&mut Lua>> =
                lua.get("prelude_buildengine")
                   .expect("Loaded prelude but prelude_buildengine table was not found");
            let mut modules = prelude_table.empty_array("modules");
            for script in scripts {
                let (name, body) = script;
                if name == "init".to_owned() {
                    main = body;
                    continue;
                }
                modules.set(name, body);
            }
        }
        lua.execute::<()>(&main).expect("Syntax error in init module of script");
        Engine { interpreter: lua }
    }
}

impl<'lua> Debug for Engine<'lua> {
    fn fmt(&self, _fmt: &mut Formatter) -> Result<(), fmt::Error> {
        Ok(())
    }
}
<commit_msg>Simplify a type hint in the script engine<commit_after>//! Contatins code relating to the engine's scripting capability.

#[cfg(test)]
mod test;

use std::collections::HashMap;
use std::fmt::{Debug, Formatter};
use std::fmt;

use hlua::Lua;
use hlua::lua_tables::LuaTable;

/// The engine lua standard library. Contains functionality relating to making a game with the engine.
///
/// Exposed as the module "buildstation" to lua code.
const ENGINE_STD: &'static str = include_str!("enginestd.lua");

/// A piece of code run before the main script.
const PRELUDE: &'static str = include_str!("prelude.lua");

/// Handles the scripts, their state, and their execution.
pub struct Engine<'lua> {
    /// The interpreter used for the scripts.
    pub interpreter: Lua<'lua>,
}

impl<'lua> Engine<'lua> {
    /// Constructs a script::Engine and loads the given scripts.
    ///
    /// The interpreter is initalized with the lua standard library, and the engine std.
    ///
    /// All scripts are loaded into the same namespace, and must return nothing when loaded.
    pub fn new(mut scripts: HashMap<String, String>) -> Self {
        scripts.insert("buildengine".to_owned(), ENGINE_STD.to_owned());
        let mut lua = Lua::new();
        lua.openlibs();
        lua.execute::<()>(PRELUDE).expect("Syntax error in prelude module of engine");
        let mut main = "".to_owned();
        {
            // Set up module table.
            let mut prelude_table: LuaTable<_> =
                lua.get("prelude_buildengine")
                   .expect("Loaded prelude but prelude_buildengine table was not found");
            let mut modules = prelude_table.empty_array("modules");
            for script in scripts {
                let (name, body) = script;
                if name == "init".to_owned() {
                    main = body;
                    continue;
                }
                modules.set(name, body);
            }
        }
        lua.execute::<()>(&main).expect("Syntax error in init module of script");
        Engine { interpreter: lua }
    }
}

impl<'lua> Debug for Engine<'lua> {
    fn fmt(&self, _fmt: &mut Formatter) -> Result<(), fmt::Error> {
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! K Means Classification
//!
//!

use linalg::matrix::Matrix;
use linalg::vector::Vector;
use learning::UnSupModel;
use rand;
use rand::Rng;

pub enum InitAlgorithm {
    Forgy,
    RandomPartition,
    KPlusPlus,
}

/// K-Means Classification model.
///
/// Contains option for centroids.
/// Specifies iterations and number of classes.
pub struct KMeansClassifier {
    pub iters: usize,
    pub k: usize,
    pub centroids: Option<Matrix<f64>>,
    pub init_algorithm: InitAlgorithm,
}

impl UnSupModel<Matrix<f64>, Vector<usize>> for KMeansClassifier {
    /// Predict classes from data.
    ///
    /// Model must be trained.
    fn predict(&self, data: Matrix<f64>) -> Vector<usize> {
        match self.centroids {
            Some(ref _c) => return self.find_closest_centroids(&data),
            None => panic!("Model has not been trained."),
        }

    }

    /// Train the classifier using input data.
    fn train(&mut self, data: Matrix<f64>) {
        self.init_centroids(&data);

        for _i in 0..self.iters {
            let idx = self.find_closest_centroids(&data);
            self.update_centroids(&data, idx);
        }
    }
}

impl KMeansClassifier {
    /// Constructs untrained k-means classifier model.
    ///
    /// Requires number of classes to be specified.
    /// Defaults to 100 iterations.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::k_means::KMeansClassifier;
    ///
    /// let model = KMeansClassifier::new(5);
    /// ```
    pub fn new(k: usize) -> KMeansClassifier {
        KMeansClassifier {
            iters: 100,
            k: k,
            centroids: None,
            init_algorithm: InitAlgorithm::Forgy,
        }
    }

    /// Initialize the centroids.
    ///
    /// Used internally within model.
    /// Currently only supports Forgy initialization.
    fn init_centroids(&mut self, data: &Matrix<f64>) {
        match self.init_algorithm {
            InitAlgorithm::Forgy => {
                self.centroids = Some(KMeansClassifier::forgy_init(self.k, data))
            }
            InitAlgorithm::RandomPartition => {
                self.centroids = Some(KMeansClassifier::ran_partition_init(self.k, data))
            }
            _ => self.centroids = Some(KMeansClassifier::forgy_init(self.k, data)),
        }
    }

    /// Find the centroid closest to each data point.
    ///
    /// Used internally within model.
    fn find_closest_centroids(&self, data: &Matrix<f64>) -> Vector<usize> {
        let mut idx = Vector::zeros(data.rows);

        match self.centroids {
            Some(ref c) => {
                for i in 0..data.rows {
                    // This works like repmat pulling out row i repeatedly.
                    let centroid_diff = c - data.select_rows(&vec![i; c.rows]);
                    let dist = &centroid_diff.elemul(&centroid_diff).sum_cols();

                    // Now take argmin and this is the centroid.
                    idx.data[i] = dist.argmin();

                }
            }
            None => panic!("Centroids not defined."),
        }

        idx
    }

    /// Updated the centroids by computing means of assigned classes.
    ///
    /// Used internally within model.
    fn update_centroids(&mut self, data: &Matrix<f64>, classes: Vector<usize>) {
        let mut new_centroids = Vec::with_capacity(self.k * data.cols);
        for i in 0..self.k {
            let mut vec_i = Vec::new();

            for j in classes.data.iter() {
                if *j == i {
                    vec_i.push(*j);
                }
            }

            let mat_i = data.select_rows(&vec_i);
            new_centroids.extend(mat_i.mean(0).data);
        }

        self.centroids = Some(Matrix::new(self.k, data.cols, new_centroids));
    }

    /// Compute initial centroids using Forgy scheme.
    ///
    /// Selects k random points in data for centroids.
    fn forgy_init(k: usize, data: &Matrix<f64>) -> Matrix<f64> {
        assert!(k <= data.rows);

        let mut random_choices = Vec::with_capacity(k);
        while random_choices.len() < k {
            let r = rand::thread_rng().gen_range(0, data.rows);

            if !random_choices.contains(&r) {
                random_choices.push(r);
            }
        }

        data.select_rows(&random_choices)
    }

    /// Compute initial centroids using random partition.
    ///
    /// Selects centroids by assigning each point randomly to a class
    /// and computing the mean of each class.
    fn ran_partition_init(k: usize, data: &Matrix<f64>) -> Matrix<f64> {
        assert!(k <= data.rows);

        let mut random_assignments = Vec::with_capacity(data.rows);

        // Populate so we have something in each class.
        for i in 0..k {
            random_assignments.push(i);
        }

        for _i in k..data.rows {
            random_assignments.push(rand::thread_rng().gen_range(0, k));
        }

        let mut init_centroids = Vec::with_capacity(k * data.cols);
        for i in 0..k {
            let mut vec_i = Vec::new();

            for j in random_assignments.iter() {
                if *j == i {
                    vec_i.push(*j);
                }
            }

            let mat_i = data.select_rows(&vec_i);
            init_centroids.extend(mat_i.mean(0).data);
        }

        Matrix::new(k, data.cols, init_centroids)
    }
}
<commit_msg>Adding documentation.<commit_after>//! K-means Classification
//!
//! Provides implementation of K-Means classification.
//!
//! # Usage
//!
//! ```
//! // Create model with k classes.
//! let mut model = KMeansClassifier::new(k);
//!
//! // Where train_data is a Matrix with features in columns.
//! model.train(train_data);
//!
//! // Where pred_data is a Matrix with features in columns.
//! let a = model.predict(pred_data);
//! ```
//!
//! Additionally you can control the initialization
//! algorithm and max number of iterations.
//!
//! # Initializations
//!
//! Three initialization algorithms are supported.
//!
//! ## Forgy initialization
//!
//! Choose initial centroids randomly from the data.
//!
//! ## Random Partition initialization
//!
//! Randomly assign each data point to one of k clusters.
//! The initial centroids are the mean of the data in their class.
//!
//! ## K-means++ initialization
//!
//! The [k-means++](https://en.wikipedia.org/wiki/K-means%2B%2B) scheme.

use linalg::matrix::Matrix;
use linalg::vector::Vector;
use learning::UnSupModel;
use rand;
use rand::Rng;

/// Initialization Algorithm enum.
pub enum InitAlgorithm {
    Forgy,
    RandomPartition,
    KPlusPlus,
}

/// K-Means Classification model.
///
/// Contains option for centroids.
/// Specifies iterations and number of classes.
pub struct KMeansClassifier {
    pub iters: usize,
    pub k: usize,
    pub centroids: Option<Matrix<f64>>,
    pub init_algorithm: InitAlgorithm,
}

impl UnSupModel<Matrix<f64>, Vector<usize>> for KMeansClassifier {
    /// Predict classes from data.
    ///
    /// Model must be trained.
    fn predict(&self, data: Matrix<f64>) -> Vector<usize> {
        match self.centroids {
            Some(ref _c) => return self.find_closest_centroids(&data),
            None => panic!("Model has not been trained."),
        }

    }

    /// Train the classifier using input data.
    fn train(&mut self, data: Matrix<f64>) {
        self.init_centroids(&data);

        for _i in 0..self.iters {
            let idx = self.find_closest_centroids(&data);
            self.update_centroids(&data, idx);
        }
    }
}

impl KMeansClassifier {
    /// Constructs untrained k-means classifier model.
    ///
    /// Requires number of classes to be specified.
    /// Defaults to 100 iterations.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::k_means::KMeansClassifier;
    ///
    /// let model = KMeansClassifier::new(5);
    /// ```
    pub fn new(k: usize) -> KMeansClassifier {
        KMeansClassifier {
            iters: 100,
            k: k,
            centroids: None,
            init_algorithm: InitAlgorithm::Forgy,
        }
    }

    /// Initialize the centroids.
    ///
    /// Used internally within model.
    /// Currently only supports Forgy initialization.
    fn init_centroids(&mut self, data: &Matrix<f64>) {
        match self.init_algorithm {
            InitAlgorithm::Forgy => {
                self.centroids = Some(KMeansClassifier::forgy_init(self.k, data))
            }
            InitAlgorithm::RandomPartition => {
                self.centroids = Some(KMeansClassifier::ran_partition_init(self.k, data))
            }
            _ => self.centroids = Some(KMeansClassifier::forgy_init(self.k, data)),
        }
    }

    /// Find the centroid closest to each data point.
    ///
    /// Used internally within model.
    fn find_closest_centroids(&self, data: &Matrix<f64>) -> Vector<usize> {
        let mut idx = Vector::zeros(data.rows);

        match self.centroids {
            Some(ref c) => {
                for i in 0..data.rows {
                    // This works like repmat pulling out row i repeatedly.
                    let centroid_diff = c - data.select_rows(&vec![i; c.rows]);
                    let dist = &centroid_diff.elemul(&centroid_diff).sum_cols();

                    // Now take argmin and this is the centroid.
                    idx.data[i] = dist.argmin();

                }
            }
            None => panic!("Centroids not defined."),
        }

        idx
    }

    /// Updated the centroids by computing means of assigned classes.
    ///
    /// Used internally within model.
    fn update_centroids(&mut self, data: &Matrix<f64>, classes: Vector<usize>) {
        let mut new_centroids = Vec::with_capacity(self.k * data.cols);
        for i in 0..self.k {
            let mut vec_i = Vec::new();

            for j in classes.data.iter() {
                if *j == i {
                    vec_i.push(*j);
                }
            }

            let mat_i = data.select_rows(&vec_i);
            new_centroids.extend(mat_i.mean(0).data);
        }

        self.centroids = Some(Matrix::new(self.k, data.cols, new_centroids));
    }

    /// Compute initial centroids using Forgy scheme.
    ///
    /// Selects k random points in data for centroids.
    fn forgy_init(k: usize, data: &Matrix<f64>) -> Matrix<f64> {
        assert!(k <= data.rows);

        let mut random_choices = Vec::with_capacity(k);
        while random_choices.len() < k {
            let r = rand::thread_rng().gen_range(0, data.rows);

            if !random_choices.contains(&r) {
                random_choices.push(r);
            }
        }

        data.select_rows(&random_choices)
    }

    /// Compute initial centroids using random partition.
    ///
    /// Selects centroids by assigning each point randomly to a class
    /// and computing the mean of each class.
    fn ran_partition_init(k: usize, data: &Matrix<f64>) -> Matrix<f64> {
        assert!(k <= data.rows);

        let mut random_assignments = Vec::with_capacity(data.rows);

        // Populate so we have something in each class.
        for i in 0..k {
            random_assignments.push(i);
        }

        for _i in k..data.rows {
            random_assignments.push(rand::thread_rng().gen_range(0, k));
        }

        let mut init_centroids = Vec::with_capacity(k * data.cols);
        for i in 0..k {
            let mut vec_i = Vec::new();

            for j in random_assignments.iter() {
                if *j == i {
                    vec_i.push(*j);
                }
            }

            let mat_i = data.select_rows(&vec_i);
            init_centroids.extend(mat_i.mean(0).data);
        }

        Matrix::new(k, data.cols, init_centroids)
    }
}
<|endoftext|>


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

// xfail-test
fn id<T>(t: T) -> T { t }

fn f<T>(v: &'r T) -> &'r fn()->T { id::<&'r fn()->T>(|| *v) } //~ ERROR ???

fn main() {
    let v = &5;
    io::println(fmt!("%d", f(v)()));
}
<commit_msg>auto merge of #5617 : catamorphism/rust/issue-4335, r=catamorphism<commit_after>// Copyright 2012-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.

fn id<T>(t: T) -> T { t }

fn f<'r, T>(v: &'r T) -> &'r fn()->T { id::<&'r fn()->T>(|| *v) } //~ ERROR cannot infer an appropriate lifetime due to conflicting requirements

fn main() {
    let v = &5;
    io::println(fmt!("%d", f(v)()));
}
<|endoftext|>