<commit_before>use std::fs::File;
use std::path::Path;
use std::io::prelude::*;
use std::sync::RwLock;
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 walkdir::{WalkDir, DirEntry};

use handlebars::Handlebars;
use serialize::json::{ToJson, Json};

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

impl Template {
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: name.to_string(),
            value: value.to_json()
        }
    }
}

pub struct HandlebarsEngine {
    pub prefix: String,
    pub suffix: String,
    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(())
        }
    }
}

fn read_file(path: &Path) -> Option<String> {
    if let Ok(mut file) = File::open(path) {
        let mut buf = String::new();
        if file.read_to_string(&mut buf).is_ok() {
            Some(buf)
        } else {
            info!("Failed to read file {}, skipped", path.display());
            None
        }
    } else {
        info!("Failed to open file {}, skipped.", path.display());
        None
    }
}

fn is_hidden_or_temp(entry: &DirEntry, suffix: &str) -> bool {
    entry.file_name().to_str()
        .and_then(|s| Some(s.starts_with(".") || s.starts_with("#") || s.ends_with(suffix)))
        .unwrap_or(false)
}

impl HandlebarsEngine {
    pub fn reload(&self) {
        let mut hbs = self.registry.write().unwrap();

        let mut prefix = self.prefix.clone();
        if !prefix.ends_with('/') {
            prefix.push('/');
        }
        let normalized_prefix = prefix;

        let prefix_path = Path::new(&normalized_prefix);
        let walker = WalkDir::new(prefix_path);

        hbs.clear_templates();
        let suffix = &self.suffix;
        for p in walker.min_depth(1).into_iter().filter(|e| e.is_ok() && !is_hidden_or_temp(e.as_ref().unwrap(), suffix)).map(|e| e.unwrap()) {
            let path = p.path();
            let disp = path.to_str().unwrap();
            let tpl_name = &disp[normalized_prefix.len() .. disp.len()-suffix.len()];
            if let Some(tpl) = read_file(&path) {
                if let Err(e) = hbs.register_template_string(tpl_name, tpl){
                    warn!("Failed to parse template {}, {}", tpl_name, e);
                }
            }
        }
    }

    pub fn from(prefix: &str, suffix: &str, custom: Handlebars) -> HandlebarsEngine {
        let eng = HandlebarsEngine {
            prefix: prefix.to_string(),
            suffix: suffix.to_string(),
            registry: RwLock::new(Box::new(custom))
        };
        eng.reload();
        eng
    }

    pub fn new(prefix: &str, suffix: &str) -> HandlebarsEngine {
        HandlebarsEngine::from(prefix, suffix, Handlebars::new())
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, r: Response) -> IronResult<Response> {
        let mut resp = r;
        let page_wrapper = resp.extensions.get::<HandlebarsEngine>().as_ref()
            .and_then(|h| {
                let hbs = self.registry.read().unwrap();
                Some(hbs.render(&h.name, &h.value))
            });

        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)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use serialize::json::ToJson;
    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_string(), "Handlebars on Iron".to_json());

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

    #[test]
    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, "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]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new("./examples/templates", ".hbs");
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore", Box::new(|_: &Context, _: &Helper, _: &Handlebars, _: &mut RenderContext| -> Result<(), RenderError> {
            Ok(())
        }));
    }
}
<commit_msg>(fix) fixed path issue<commit_after>use std::fs::File;
use std::env::current_dir;
use std::path::{Path, PathBuf};
use std::io::prelude::*;
use std::sync::RwLock;
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 walkdir::{WalkDir, DirEntry};

use handlebars::Handlebars;
use serialize::json::{ToJson, Json};

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

impl Template {
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: name.to_string(),
            value: value.to_json()
        }
    }
}

pub struct HandlebarsEngine {
    pub prefix: String,
    pub suffix: String,
    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(())
        }
    }
}

fn read_file(path: &Path) -> Option<String> {
    if let Ok(mut file) = File::open(path) {
        let mut buf = String::new();
        if file.read_to_string(&mut buf).is_ok() {
            Some(buf)
        } else {
            info!("Failed to read file {}, skipped", path.display());
            None
        }
    } else {
        info!("Failed to open file {}, skipped.", path.display());
        None
    }
}

fn filter_file(entry: &DirEntry, suffix: &str) -> bool {
    entry.file_name().to_str()
        .and_then(|s| Some(s.starts_with(".") || s.starts_with("#") || !s.ends_with(suffix)))
        .unwrap_or(false)
}

impl HandlebarsEngine {
    pub fn reload(&self) {
        let mut hbs = self.registry.write().unwrap();
        match current_dir()  {
            Ok(current_path) => {
                let mut prefix_path = PathBuf::from(current_path);
                prefix_path.push(self.prefix.clone());
                let template_path = prefix_path.as_path();

                info!("Loading templates from path {}", template_path.display());
                let walker = WalkDir::new(template_path);

                hbs.clear_templates();
                let suffix = &self.suffix;
                let prefix_len = template_path.as_os_str().to_str().unwrap().len();
                for p in walker.min_depth(1).into_iter().filter(|e| e.is_ok() && !filter_file(e.as_ref().unwrap(), suffix)).map(|e| e.unwrap()) {
                    let path = p.path();
                    let disp = path.to_str().unwrap();
                    debug!("getting file {}", disp);
                    let tpl_name = &disp[prefix_len .. disp.len()-suffix.len()];
                    if let Some(tpl) = read_file(&path) {
                        if let Err(e) = hbs.register_template_string(tpl_name, tpl){
                            warn!("Failed to parse template {}, {}", tpl_name, e);
                        } else {
                            info!("Added template {}", tpl_name);
                        }
                    }
                }
            },
            Err(e) => {
                error!("Failed to get current directory due to {}", e);
            }
        }
    }

    pub fn from(prefix: &str, suffix: &str, custom: Handlebars) -> HandlebarsEngine {
        let eng = HandlebarsEngine {
            prefix: prefix.to_string(),
            suffix: suffix.to_string(),
            registry: RwLock::new(Box::new(custom))
        };
        eng.reload();
        eng
    }

    pub fn new(prefix: &str, suffix: &str) -> HandlebarsEngine {
        HandlebarsEngine::from(prefix, suffix, Handlebars::new())
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, r: Response) -> IronResult<Response> {
        let mut resp = r;
        let page_wrapper = resp.extensions.get::<HandlebarsEngine>().as_ref()
            .and_then(|h| {
                let hbs = self.registry.read().unwrap();
                Some(hbs.render(&h.name, &h.value))
            });

        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)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use serialize::json::ToJson;
    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_string(), "Handlebars on Iron".to_json());

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

    #[test]
    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, "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]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new("./examples/templates", ".hbs");
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore", Box::new(|_: &Context, _: &Helper, _: &Handlebars, _: &mut RenderContext| -> Result<(), RenderError> {
            Ok(())
        }));
    }
}
<|endoftext|>


<commit_before>//! An efficient Fast Fourier transform.
//!
//! A `Transformer` must first be created to perform FFTs. The transformer
//! stores precomputed information to speed up the transform, and can only be
//! used to perform FFTs of the chosen size.

use std::f32::consts::PI;
use std::vec::Vec;

use num::complex::Complex32;
use num::traits::Zero;

/// A container for precomputed values to perform FFTs of a fixed size.
pub struct Transformer {
    size: usize,
    bit_reverses: Vec<usize>,
    twiddles: Vec<Complex32>,
}

impl Transformer {
    /// Initialize a transformer to perform FFTs of the provided size, rounded
    /// up to the nearest power of two.
    pub fn new(size: usize) -> Transformer {
        // Only operate in powers of two
        let bufsize = size.next_power_of_two();

        // Populate the bit reverses
        // We only use the lower log2(size) bits to express the index
        let mut bit_reverses = Vec::with_capacity(bufsize);
        for i in (0 .. size) {
            let br = bit_reverse(i as u32, int_log(bufsize as u32));
            bit_reverses.push(br as usize);
        }

        // Populate the twiddle factors w_n^i
        // w_n = exp(-j*2*pi*n/N)
        let mut twiddles = Vec::with_capacity(bufsize);
        let exponent = Complex32::new(0.0, -2.0*PI/(bufsize as f32));
        for i in (0 .. bufsize) {
            let c1 = exponent.scale(i as f32);
            let c = Complex32::new(c1.im.cos(), c1.im.sin()).scale(c1.re.exp());
            twiddles.push(c);
        }

        Transformer { size: bufsize, bit_reverses: bit_reverses,
            twiddles: twiddles }
    }

    /// Return the size FFT this Transformer performs.
    pub fn get_size(&self) -> usize {
        self.size
    }

    /// Perform an FFT on `input`, and place the result in `output`.
    ///
    /// The input is zero padded if less than `size` samples are provided, and
    /// truncated if more than `size` samples are provided.
    pub fn fft(&self, input: &[Complex32], output: &mut[Complex32]) {
        self.transform(input, output, false);
    }

    /// Perform an inverse FFT on `input`, and place the result in `output`.
    ///
    /// The input is zero padded if less than `size` samples are provided, and
    /// truncated if more than `size` samples are provided.
    pub fn ifft(&self, input: &[Complex32], output: &mut[Complex32]) {
        self.transform(input, output, true);
    }

    /// Perform the actual transform on `input`, placing the result in `output`.
    ///
    /// This function performs both forward and backwards transforms, since
    /// there are only minor algorithmic differences in the beginning and end
    /// of transformation.
    ///
    /// The input is zero padded if less than `size` samples are provided, and
    /// truncated if more than `size` samples are provided.
    fn transform(&self, input: &[Complex32], output: &mut[Complex32],
                 inverse: bool) {
        // Copy the input into bit reverse order, zero padding if necessary,
        // conjugating if we are inverse transforming
        for i in (0 .. input.len()) {
            output[self.bit_reverses[i]] =
                if inverse {
                    input[i].conj()
                } else {
                    input[i]
                }
        }
        for i in self.bit_reverses[input.len() .. self.size].iter() {
            output[*i] = Complex32::zero();
        }

        // Iteratively perform FFT, starting at 2 points
        let mut n = 2;
        while n <= self.size {
            // For each of the small FFTs
            for set in (0 .. self.size/n) {
                // For each pair of n
                for i in (0 .. n/2) {
                    let ilo = n*set + i;
                    let ihi = ilo + n/2;

                    // Grab out the lower and upper n
                    let lower = output[ilo];
                    let upper = output[ihi] * self.twiddles[self.size/n * i];

                    // Assign them back using a butterfly
                    output[ilo] = lower + upper;
                    output[ihi] = lower - upper;
                }
            }

            // Double the number of points per FFT
            n *= 2;
        }

        // If we are inverse transforming, conjugate and normalize the output
        if inverse {
            for i in (0 .. self.size) {
                output[i] = output[i].conj().scale(1.0/(self.size as f32));
            }
        }
    }
}

/// Return the bit reverse of `n`, for the lower `bits` bits.
///
/// For small examples, the bit reverse of 0b00011010 is 0b01011000, but the bit
/// reverse of just the lower 5 bits is 0b00001011.
fn bit_reverse(n: u32, bits: u32) -> u32 {
    let mut i = n;
    i = (i >> 16) | (i << 16);
    i = ((i & 0xFF00FF00) >> 8) | ((i & 0x00FF00FF) << 8);
    i = ((i & 0xF0F0F0F0) >> 4) | ((i & 0x0F0F0F0F) << 4);
    i = ((i & 0xCCCCCCCC) >> 2) | ((i & 0x33333333) << 2);
    i = ((i & 0xAAAAAAAA) >> 1) | ((i & 0x55555555) << 1);
    i >> ((32 - bits) as u32)
}

/// Return the log base 2 of n, rounded up.
fn int_log(n: u32) -> u32 {
    let mut i = n-1; // correct for exact powers of 2
    let mut res = 0;
    while i > 0 {
        i = i >> 1;
        res += 1;
    }
    res
}

// Unit tests...
#[cfg(test)]
mod test {
    use std::vec::Vec;

    use num::complex::Complex32;
    use num::traits::{One, Zero};

    use super::{Transformer, int_log, bit_reverse};

    // For floating point comparison
    static EPSILON: f32 = 1e-6;

    /// Tests int_log with many values
    #[test]
    fn test_int_log() {
        assert_eq!(int_log(1), 0);
        assert_eq!(int_log(2), 1);
        assert_eq!(int_log(3), 2);
        assert_eq!(int_log(4), 2);
        assert_eq!(int_log(7), 3);
        assert_eq!(int_log(8), 3);
        assert_eq!(int_log(31), 5);
        assert_eq!(int_log(32), 5);
    }

    /// Tests bit_reverse.
    #[test]
    fn test_bit_reverse() {
        assert_eq!(bit_reverse(0x00000000, 32), 0x00000000);
        assert_eq!(bit_reverse(0xFFFFFFFF, 32), 0xFFFFFFFF);
        assert_eq!(bit_reverse(0x00000001, 32), 0x80000000);
        assert_eq!(bit_reverse(0x11111111, 32), 0x88888888);
        assert_eq!(bit_reverse(0x234f9e01, 32), 0x8079f2c4); //random
        assert_eq!(bit_reverse(0x00000001, 4), 0x00000008);
        assert_eq!(bit_reverse(0x0000000F, 4), 0x0000000F);
    }

    /// Tests the FFT of an impulse function.
    ///
    /// Analytically, an impulse function has a constant fourier transform.
    #[test]
    fn test_fft_impulse() {
        let mut impulse = Vec::with_capacity(8);
        let mut out = Vec::with_capacity(8);
        for i in (0 .. 8) {
            impulse.push(if i == 0 { Complex32::one() } else { Complex32::zero() });
            out.push(Complex32::zero());
        }

        let t = Transformer::new(8);
        t.fft(&impulse, &mut out);

        for c in out.iter() {
            assert!(c.eq(&Complex32::one()))
        }
    }

    /// Tests the IFFT of an impulse function.
    ///
    /// Analytically, a constant frequency domain results in an impulse
    /// function.
    #[test]
    fn test_ifft_impulse() {
        let mut impulse = Vec::with_capacity(8);
        let mut out = Vec::with_capacity(8);
        for _i in (0 .. 8) {
            impulse.push(Complex32::one());
            out.push(Complex32::zero());
        }

        let t = Transformer::new(8);
        t.ifft(&impulse, &mut out);

        assert!(out[0].eq(&Complex32::one()));
        for c in out[1 .. 8].iter() {
            assert!(c.eq(&Complex32::zero()));
        }
    }

    /// Tests that the identify property, i.e. IFFT(FTT(f)) == f
    #[test]
    fn test_fft_identity() {
        let mut input = Vec::with_capacity(8);
        let mut fft = Vec::with_capacity(8);
        let mut out = Vec::with_capacity(8);
        for i in (0 .. 8) {
            input.push(Complex32::new((i+1) as f32, 0.0));
            fft.push(Complex32::zero());
            out.push(Complex32::zero());
        }

        let t = Transformer::new(8);
        t.fft(&input, &mut fft);
        t.ifft(&fft, &mut out);

        for i in (0 .. 7) {
            println!("{}",out[i].re - ((i+1) as f32));
            assert!(out[i].re - ((i+1) as f32) < EPSILON);
            assert!(out[i].im < EPSILON);
        }
    }

    /// Tests that the Transformer properly handles input buffers that are too
    /// short by zero padding them.
    #[test]
    fn test_fft_zero_pad() {
        let mut input = Vec::with_capacity(7);
        let mut fft = Vec::with_capacity(8);
        let mut out = Vec::with_capacity(8);
        for i in (0 .. 8) {
            if i < 7 {
                input.push(Complex32::new((i+1) as f32, 0.0));
            }
            fft.push(Complex32::zero());
            out.push(Complex32::zero());
        }

        let t = Transformer::new(8);
        t.fft(&input, &mut fft);
        t.ifft(&fft, &mut out);

        for i in (0 .. 7) {
            println!("{}",out[i].re - ((i+1) as f32));
            assert!(out[i].re - ((i+1) as f32) < EPSILON);
            assert!(out[i].im < EPSILON);
        }
    }
}
<commit_msg>Add FFT example documentation<commit_after>//! An efficient Fast Fourier transform.
//!
//! A `Transformer` must first be created to perform FFTs. The transformer
//! stores precomputed information to speed up the transform, and can only be
//! used to perform FFTs of the chosen size.
//!
//! # Example
//!
//! The following demonstrates how to use the `Transformer` to perform an 8-point FFT.
//!
//! ```
//! # extern crate num;
//! # extern crate oxcable;
//! # fn main() {
//! use num::complex::Complex32;
//! use num::traits::Zero;
//! use oxcable::utils::fft;
//!
//! // Initialize the FFT
//! let transformer = fft::Transformer::new(8);
//!
//! // Generate an input signal
//! let mut input = Vec::with_capacity(8);
//! for i in 0..8 {
//!     input.push(Complex32::new(i as f32, 0.0));
//! }
//!
//! // Generate an empty output buffer
//! let mut output = vec![Complex32::zero(); 8];
//!
//! // Perform the FFT
//! transformer.fft(&input, &mut output);
//! # }
//! ```
//!
//! After this example, `output` will contain the FFT of `input`.

use std::f32::consts::PI;
use std::vec::Vec;

use num::complex::Complex32;
use num::traits::Zero;

/// A container for precomputed values to perform FFTs of a fixed size.
pub struct Transformer {
    size: usize,
    bit_reverses: Vec<usize>,
    twiddles: Vec<Complex32>,
}

impl Transformer {
    /// Initialize a transformer to perform FFTs of the provided size, rounded
    /// up to the nearest power of two.
    pub fn new(size: usize) -> Transformer {
        // Only operate in powers of two
        let bufsize = size.next_power_of_two();

        // Populate the bit reverses
        // We only use the lower log2(size) bits to express the index
        let mut bit_reverses = Vec::with_capacity(bufsize);
        for i in (0 .. size) {
            let br = bit_reverse(i as u32, int_log(bufsize as u32));
            bit_reverses.push(br as usize);
        }

        // Populate the twiddle factors w_n^i
        // w_n = exp(-j*2*pi*n/N)
        let mut twiddles = Vec::with_capacity(bufsize);
        let exponent = Complex32::new(0.0, -2.0*PI/(bufsize as f32));
        for i in (0 .. bufsize) {
            let c1 = exponent.scale(i as f32);
            let c = Complex32::new(c1.im.cos(), c1.im.sin()).scale(c1.re.exp());
            twiddles.push(c);
        }

        Transformer { size: bufsize, bit_reverses: bit_reverses,
            twiddles: twiddles }
    }

    /// Return the size FFT this Transformer performs.
    pub fn get_size(&self) -> usize {
        self.size
    }

    /// Perform an FFT on `input`, and place the result in `output`.
    ///
    /// The input is zero padded if less than `size` samples are provided, and
    /// truncated if more than `size` samples are provided.
    pub fn fft(&self, input: &[Complex32], output: &mut[Complex32]) {
        self.transform(input, output, false);
    }

    /// Perform an inverse FFT on `input`, and place the result in `output`.
    ///
    /// The input is zero padded if less than `size` samples are provided, and
    /// truncated if more than `size` samples are provided.
    pub fn ifft(&self, input: &[Complex32], output: &mut[Complex32]) {
        self.transform(input, output, true);
    }

    /// Perform the actual transform on `input`, placing the result in `output`.
    ///
    /// This function performs both forward and backwards transforms, since
    /// there are only minor algorithmic differences in the beginning and end
    /// of transformation.
    ///
    /// The input is zero padded if less than `size` samples are provided, and
    /// truncated if more than `size` samples are provided.
    fn transform(&self, input: &[Complex32], output: &mut[Complex32],
                 inverse: bool) {
        // Copy the input into bit reverse order, zero padding if necessary,
        // conjugating if we are inverse transforming
        for i in (0 .. input.len()) {
            output[self.bit_reverses[i]] =
                if inverse {
                    input[i].conj()
                } else {
                    input[i]
                }
        }
        for i in self.bit_reverses[input.len() .. self.size].iter() {
            output[*i] = Complex32::zero();
        }

        // Iteratively perform FFT, starting at 2 points
        let mut n = 2;
        while n <= self.size {
            // For each of the small FFTs
            for set in (0 .. self.size/n) {
                // For each pair of n
                for i in (0 .. n/2) {
                    let ilo = n*set + i;
                    let ihi = ilo + n/2;

                    // Grab out the lower and upper n
                    let lower = output[ilo];
                    let upper = output[ihi] * self.twiddles[self.size/n * i];

                    // Assign them back using a butterfly
                    output[ilo] = lower + upper;
                    output[ihi] = lower - upper;
                }
            }

            // Double the number of points per FFT
            n *= 2;
        }

        // If we are inverse transforming, conjugate and normalize the output
        if inverse {
            for i in (0 .. self.size) {
                output[i] = output[i].conj().scale(1.0/(self.size as f32));
            }
        }
    }
}

/// Return the bit reverse of `n`, for the lower `bits` bits.
///
/// For small examples, the bit reverse of 0b00011010 is 0b01011000, but the bit
/// reverse of just the lower 5 bits is 0b00001011.
fn bit_reverse(n: u32, bits: u32) -> u32 {
    let mut i = n;
    i = (i >> 16) | (i << 16);
    i = ((i & 0xFF00FF00) >> 8) | ((i & 0x00FF00FF) << 8);
    i = ((i & 0xF0F0F0F0) >> 4) | ((i & 0x0F0F0F0F) << 4);
    i = ((i & 0xCCCCCCCC) >> 2) | ((i & 0x33333333) << 2);
    i = ((i & 0xAAAAAAAA) >> 1) | ((i & 0x55555555) << 1);
    i >> ((32 - bits) as u32)
}

/// Return the log base 2 of n, rounded up.
fn int_log(n: u32) -> u32 {
    let mut i = n-1; // correct for exact powers of 2
    let mut res = 0;
    while i > 0 {
        i = i >> 1;
        res += 1;
    }
    res
}

// Unit tests...
#[cfg(test)]
mod test {
    use std::vec::Vec;

    use num::complex::Complex32;
    use num::traits::{One, Zero};

    use super::{Transformer, int_log, bit_reverse};

    // For floating point comparison
    static EPSILON: f32 = 1e-6;

    /// Tests int_log with many values
    #[test]
    fn test_int_log() {
        assert_eq!(int_log(1), 0);
        assert_eq!(int_log(2), 1);
        assert_eq!(int_log(3), 2);
        assert_eq!(int_log(4), 2);
        assert_eq!(int_log(7), 3);
        assert_eq!(int_log(8), 3);
        assert_eq!(int_log(31), 5);
        assert_eq!(int_log(32), 5);
    }

    /// Tests bit_reverse.
    #[test]
    fn test_bit_reverse() {
        assert_eq!(bit_reverse(0x00000000, 32), 0x00000000);
        assert_eq!(bit_reverse(0xFFFFFFFF, 32), 0xFFFFFFFF);
        assert_eq!(bit_reverse(0x00000001, 32), 0x80000000);
        assert_eq!(bit_reverse(0x11111111, 32), 0x88888888);
        assert_eq!(bit_reverse(0x234f9e01, 32), 0x8079f2c4); //random
        assert_eq!(bit_reverse(0x00000001, 4), 0x00000008);
        assert_eq!(bit_reverse(0x0000000F, 4), 0x0000000F);
    }

    /// Tests the FFT of an impulse function.
    ///
    /// Analytically, an impulse function has a constant fourier transform.
    #[test]
    fn test_fft_impulse() {
        let mut impulse = Vec::with_capacity(8);
        let mut out = Vec::with_capacity(8);
        for i in (0 .. 8) {
            impulse.push(if i == 0 { Complex32::one() } else { Complex32::zero() });
            out.push(Complex32::zero());
        }

        let t = Transformer::new(8);
        t.fft(&impulse, &mut out);

        for c in out.iter() {
            assert!(c.eq(&Complex32::one()))
        }
    }

    /// Tests the IFFT of an impulse function.
    ///
    /// Analytically, a constant frequency domain results in an impulse
    /// function.
    #[test]
    fn test_ifft_impulse() {
        let mut impulse = Vec::with_capacity(8);
        let mut out = Vec::with_capacity(8);
        for _i in (0 .. 8) {
            impulse.push(Complex32::one());
            out.push(Complex32::zero());
        }

        let t = Transformer::new(8);
        t.ifft(&impulse, &mut out);

        assert!(out[0].eq(&Complex32::one()));
        for c in out[1 .. 8].iter() {
            assert!(c.eq(&Complex32::zero()));
        }
    }

    /// Tests that the identify property, i.e. IFFT(FTT(f)) == f
    #[test]
    fn test_fft_identity() {
        let mut input = Vec::with_capacity(8);
        let mut fft = Vec::with_capacity(8);
        let mut out = Vec::with_capacity(8);
        for i in (0 .. 8) {
            input.push(Complex32::new((i+1) as f32, 0.0));
            fft.push(Complex32::zero());
            out.push(Complex32::zero());
        }

        let t = Transformer::new(8);
        t.fft(&input, &mut fft);
        t.ifft(&fft, &mut out);

        for i in (0 .. 7) {
            println!("{}",out[i].re - ((i+1) as f32));
            assert!(out[i].re - ((i+1) as f32) < EPSILON);
            assert!(out[i].im < EPSILON);
        }
    }

    /// Tests that the Transformer properly handles input buffers that are too
    /// short by zero padding them.
    #[test]
    fn test_fft_zero_pad() {
        let mut input = Vec::with_capacity(7);
        let mut fft = Vec::with_capacity(8);
        let mut out = Vec::with_capacity(8);
        for i in (0 .. 8) {
            if i < 7 {
                input.push(Complex32::new((i+1) as f32, 0.0));
            }
            fft.push(Complex32::zero());
            out.push(Complex32::zero());
        }

        let t = Transformer::new(8);
        t.fft(&input, &mut fft);
        t.ifft(&fft, &mut out);

        for i in (0 .. 7) {
            println!("{}",out[i].re - ((i+1) as f32));
            assert!(out[i].re - ((i+1) as f32) < EPSILON);
            assert!(out[i].im < EPSILON);
        }
    }
}
<|endoftext|>


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

pub struct RawSource<R>(io::Lines<io::BufReader<R>>) where R: io::Read;

pub struct RawSink<W>(io::LineWriter<W>) where W: io::Write;

#[inline]
pub fn source<R>(r: R) -> RawSource<R> where R: io::Read
{
    use std::io::BufRead;
    RawSource(io::BufReader::new(r).lines())
}

#[inline]
pub fn sink<W>(w: W) -> RawSink<W> where W: io::Write
{
    RawSink(io::LineWriter::new(w))
}

impl<R> value::Source for RawSource<R> where R: io::Read
{
    #[inline]
    fn read(&mut self) -> error::Result<Option<value::Value>> {
        match self.0.next() {
            Some(Ok(v)) => Ok(Some(value::Value::String(v))),
            Some(Err(e)) => Err(error::Error::from(e)),
            None => Ok(None),
        }
    }
}

impl<W> value::Sink for RawSink<W> where W: io::Write
{
    #[inline]
    fn write(&mut self, value: value::Value) -> error::Result<()> {
        use std::io::Write;
        match value {
            value::Value::String(s) => {
                self.0.write(s.as_bytes())?;
                self.0.write(b"\n")?;
                Ok(())
            }
            value::Value::Bytes(b) => {
                self.0.write(&b)?;
                self.0.write(b"\n")?;
                Ok(())
            }
            x => bail!("raw can only output strings and bytes, got: {:?}", x)
        }
    }
}
<commit_msg>Support writing characters as raw<commit_after>use error;
use std::io;
use value;

pub struct RawSource<R>(io::Lines<io::BufReader<R>>) where R: io::Read;

pub struct RawSink<W>(io::LineWriter<W>) where W: io::Write;

#[inline]
pub fn source<R>(r: R) -> RawSource<R> where R: io::Read
{
    use std::io::BufRead;
    RawSource(io::BufReader::new(r).lines())
}

#[inline]
pub fn sink<W>(w: W) -> RawSink<W> where W: io::Write
{
    RawSink(io::LineWriter::new(w))
}

impl<R> value::Source for RawSource<R> where R: io::Read
{
    #[inline]
    fn read(&mut self) -> error::Result<Option<value::Value>> {
        match self.0.next() {
            Some(Ok(v)) => Ok(Some(value::Value::String(v))),
            Some(Err(e)) => Err(error::Error::from(e)),
            None => Ok(None),
        }
    }
}

impl<W> value::Sink for RawSink<W> where W: io::Write
{
    #[inline]
    fn write(&mut self, value: value::Value) -> error::Result<()> {
        use std::io::Write;
        match value {
            value::Value::String(s) => {
                self.0.write(s.as_bytes())?;
                self.0.write(b"\n")?;
                Ok(())
            }
            value::Value::Bytes(b) => {
                self.0.write(&b)?;
                self.0.write(b"\n")?;
                Ok(())
            }
            value::Value::Char(c) => {
                write!(self.0, "{}\n", c)?;
                Ok(())
            }
            x => bail!("raw can only output strings, bytes and chars, got: {:?}", x)
        }
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>will work on main<commit_after>

fn main() {
    println!("Hello, world!");
}
<|endoftext|>


<commit_before>extern crate rand;

use rand::{thread_rng, Rng};

#[derive(Debug, Clone, PartialEq)]
enum Node {
    A,
    B,
    C,
    D,
    E,
}

use Node::*;

const N_NODES: usize = 5;
static AVAIL_NODES: [Node; N_NODES] = [A, B, C, D, E];

#[derive(Debug)]
struct Ant {
    memory: Vec<Node>,
    available: Vec<Node>,
}

impl Ant {
    fn new(init_node: &Node) -> Ant {
        let mut vec = Vec::new();
        vec.push(init_node.clone());
        let mut available: Vec<Node> = Vec::new();
        for node in &AVAIL_NODES {
            if *init_node != *node {
                available.push(node.clone());
            }
        }

        Ant {
            memory: vec,
            available: available,
        }
    }
}

#[derive(Debug)]
struct AntColony {
    rho: f64,
    alpha: f64,
    beta: f64,
    q: i32,
    num_ant: usize,
    num_it: usize,
    distance: [[f32; N_NODES]; N_NODES],
    visibility: [[f64; N_NODES]; N_NODES],
    pheromone: [[f64; N_NODES]; N_NODES],
}

impl AntColony {
    fn new(
        rho: f64,
        alpha: f64,
        beta: f64,
        q: i32,
        init_phero: f64,
        num_ant: usize,
        num_it: usize,
    ) -> AntColony {
        let distance = [
            [0.0, 12.0, 3.0, 23.0, 1.0],
            [12.0, 0.0, 9.0, 18.0, 3.0],
            [3.0, 9.0, 0.0, 89.0, 56.0],
            [23.0, 18.0, 89.0, 0.0, 87.0],
            [1.0, 3.0, 56.0, 87.0, 0.0],
        ];

        let mut visibility = [[0.0; 5]; 5];
        let mut pheromone = [[0.0; 5]; 5];
        for y in 0..N_NODES {
            for x in 0..N_NODES {
                if x != y {
                    visibility[y][x] = 1.0 / distance[y][x] as f64;
                    pheromone[y][x] = init_phero;
                }
            }
        }

        AntColony {
            rho: rho,
            alpha: alpha,
            beta: beta,
            q: q,
            num_ant: num_ant,
            num_it: num_it,
            distance: distance,
            visibility: visibility,
            pheromone: pheromone,
        }
    }

    // fn print_matrix(matrix: &[[f64; 5]; 5], descr: &str) {
    //     println!("{}", descr);[curr_indx][next_indx];
    //     for y in 0..5 {
    //         for x in 0..5 {
    //             print!("{}\t", matrix[y][x]);ant.memory
    //         }
    //         println!("");
    //     }
    // }

    fn compute_available_nodes(&self, ant: &mut Ant) {
        let current = ant.memory.last().unwrap();
        let mut to_remove = ant.available.len();
        for (indx, next) in ant.available.iter().enumerate() {
            if current == next {
                to_remove = indx;
                break;
            }
        }

        ant.available.remove(to_remove);
    }

    fn compute_next_node(&self, ant: &Ant) -> Node {
        let mut sum = 0.0;
        let current = ant.memory.last().unwrap();
        let mut vec_tnp = Vec::new();
        for next in &ant.available {
            let curr_indx = current.clone() as usize;
            let next_indx = next.clone() as usize;
            let t = self.pheromone[curr_indx][next_indx].powf(self.alpha);
            let n = self.visibility[curr_indx][next_indx].powf(self.beta);
            let t_n = t * n;
            sum += t_n;
            println!(
                "{:?}-{:?}: t = {}\tn = {}\tt*n = {}",
                current,
                next,
                t,
                n,
                t_n
            );
            vec_tnp.push(t_n);
        }

        println!("Suma: {}", sum);

        for (indx, next) in ant.available.iter().enumerate() {
            let prob = vec_tnp[indx] / sum;
            println!("{:?}-{:?}: prob = {}", current, next, prob);
            vec_tnp[indx] = prob;
        }

        let mut rng = thread_rng();
        let num = rng.gen::<f64>();
        let mut s = 0.0;
        let mut next_indx = 0;
        for (i, &prob) in vec_tnp.iter().enumerate() {
            s += prob;
            if num < s {
                next_indx = i;
                break;
            }
        }

        println!("Numero aleatorio para la Probabilidad: {}", num);

        ant.available[next_indx].clone()
    }

    fn get_path_cost(&self, path: &[Node]) -> f32 {
        let mut dist = 0.0;
        for i in 1..path.len() {
            dist += self.distance[path[i - 1].clone() as usize][path[i].clone() as usize];
        }
        dist
    }

    fn update_pheromone(&mut self, vec_paths: Vec<(&Vec<Node>, f32)>) {
        for i in 0..N_NODES {
            for j in 0..N_NODES {
                if i != j {
                    self.pheromone[i][j] = self.pheromone[i][j] * self.rho;
                    print!(
                        "{:?}-{:?}: Feromona = {}",
                        AVAIL_NODES[i],
                        AVAIL_NODES[j],
                        self.pheromone[i][j]
                    );
                    for &(path, cost) in &vec_paths {
                        // let f_x = self.pheromone[i][j] * self.rho;
                        let mut f_x = 0.0;
                        for x in 1..path.len() {
                            if path[x] == AVAIL_NODES[i] {
                                if path[x - 1] == AVAIL_NODES[j] {
                                    f_x = 1.0 / cost;
                                }
                            } else if path[x] == AVAIL_NODES[j] {
                                if path[x - 1] == AVAIL_NODES[i] {
                                    f_x = 1.0 / cost;
                                }
                            }
                        }
                        print!(" + {}", f_x);
                        self.pheromone[i][j] += f_x as f64;
                    }
                    println!(" = {}", self.pheromone[i][j]);
                }
            }
        }
    }

    fn ant_iteration(&mut self) {
        // print_matrix(&SCORES, "Matriz Distancia");
        // print_matrix(&self.visibility, "Matriz Visibilidad");
        // print_matrix(&self.pheromone, "Matriz Feromona");
        let mut best_global_ant: (Vec<Node>, f32) = (Vec::new(), 100000000.0);
        for iter in 0..self.num_it {
            println!("\nIteración {}", iter +1 );
            println!("Matriz Distancia\n{:?}", &self.distance);
            println!("Matriz Visibilidad\n{:?}", &self.visibility);
            println!("Matriz Feromona\n{:?}", &self.pheromone);

            let mut best_iter_ant: (Vec<Node>, f32) = (Vec::new(), 100000000.0);

            let mut vec_ants = Vec::new();
            for i in 0..self.num_ant {
                println!("Hormiga {}", i + 1);
                let start_node = D;
                let mut ant = Ant::new(&start_node);
                println!("Ciudad inicial: {:?}", start_node);
                for _ in 0..N_NODES - 1 {
                    let next = self.compute_next_node(&ant);
                    println!("Ciudad Siguiente: {:?}\n", next);
                    ant.memory.push(next);
                    self.compute_available_nodes(&mut ant);
                }
                println!("Hormiga {}: {:?}\n", i + 1, ant.memory);
                vec_ants.push(ant.memory);
            }

            let mut tupl_vec = Vec::new();
            for (indx, ant) in vec_ants.iter().enumerate() {
                let cost = self.get_path_cost(ant);
                println!(
                    "Hormiga {} {:?} - Costo: {}",
                    indx + 1,
                    ant,
                    cost
                );
                if cost < best_iter_ant.1 {
                    best_iter_ant.0 = ant.clone();
                    best_iter_ant.1 = cost;
                }
                if cost < best_global_ant.1 {
                    best_global_ant.0 = ant.clone();
                    best_global_ant.1 = cost;
                }
                tupl_vec.push((ant, cost));
            }
            println!("----------\nMejor Hormiga Iteración {}: {:?} - Costo: {}\n----------", iter + 1, best_iter_ant.0, best_iter_ant.1);

            self.update_pheromone(tupl_vec);
        }

        println!("----------\nMejor Hormiga Global: {:?} - Costo: {}\n----------", best_global_ant.0, best_global_ant.1);
    }
}

fn main() {
    let mut colony = AntColony::new(0.99, 1.0, 1.0, 1, 0.1, 3, 100);
    colony.ant_iteration();
}
<commit_msg>Init files<commit_after>extern crate rand;

use rand::{thread_rng, Rng};

#[derive(Debug, Clone, PartialEq)]
enum Node {
    A,
    B,
    C,
    D,
    E,
    F,
}

use Node::*;

const N_NODES: usize = 6;
static AVAIL_NODES: [Node; N_NODES] = [A, B, C, D, E, F];

#[derive(Debug)]
struct Ant {
    memory: Vec<Node>,
    available: Vec<Node>,
}

impl Ant {
    fn new(init_node: &Node) -> Ant {
        let mut vec = Vec::new();
        vec.push(init_node.clone());
        let mut available: Vec<Node> = Vec::new();
        for node in &AVAIL_NODES {
            if *init_node != *node {
                available.push(node.clone());
            }
        }

        Ant {
            memory: vec,
            available: available,
        }
    }
}

#[derive(Debug)]
struct AntColony {
    rho: f64,
    alpha: f64,
    beta: f64,
    q: i32,
    num_ant: usize,
    num_it: usize,
    distance: [[f32; N_NODES]; N_NODES],
    visibility: [[f64; N_NODES]; N_NODES],
    pheromone: [[f64; N_NODES]; N_NODES],
}

impl AntColony {
    fn new(
        rho: f64,
        alpha: f64,
        beta: f64,
        q: i32,
        init_phero: f64,
        num_ant: usize,
        num_it: usize,
    ) -> AntColony {
        let distance = [
            [0.0, 12.0, 3.0, 23.0, 1.0, 5.0],
            [12.0, 0.0, 9.0, 18.0, 3.0, 41.0],
            [3.0, 9.0, 0.0, 89.0, 56.0, 21.0],
            [23.0, 18.0, 89.0, 0.0, 87.0, 46.5],
            [1.0, 3.0, 56.0, 87.0, 0.0, 55.0],
            [5.0, 41.0, 21.0, 46.0, 55.0, 0.0]
        ];

        let mut visibility = [[0.0; N_NODES]; N_NODES];
        let mut pheromone = [[0.0; N_NODES]; N_NODES];
        for y in 0..N_NODES {
            for x in 0..N_NODES {
                if x != y {
                    visibility[y][x] = 1.0 / distance[y][x] as f64;
                    pheromone[y][x] = init_phero;
                }
            }
        }

        AntColony {
            rho: rho,
            alpha: alpha,
            beta: beta,
            q: q,
            num_ant: num_ant,
            num_it: num_it,
            distance: distance,
            visibility: visibility,
            pheromone: pheromone,
        }
    }

    // fn print_matrix(matrix: &[[f64; 5]; 5], descr: &str) {
    //     println!("{}", descr);[curr_indx][next_indx];
    //     for y in 0..5 {
    //         for x in 0..5 {
    //             print!("{}\t", matrix[y][x]);ant.memory
    //         }
    //         println!("");
    //     }
    // }

    fn compute_available_nodes(&self, ant: &mut Ant) {
        let current = ant.memory.last().unwrap();
        let mut to_remove = ant.available.len();
        for (indx, next) in ant.available.iter().enumerate() {
            if current == next {
                to_remove = indx;
                break;
            }
        }

        ant.available.remove(to_remove);
    }

    fn compute_next_node(&self, ant: &Ant) -> Node {
        let mut sum = 0.0;
        let current = ant.memory.last().unwrap();
        let mut vec_tnp = Vec::new();
        for next in &ant.available {
            let curr_indx = current.clone() as usize;
            let next_indx = next.clone() as usize;
            let t = self.pheromone[curr_indx][next_indx].powf(self.alpha);
            let n = self.visibility[curr_indx][next_indx].powf(self.beta);
            let t_n = t * n;
            sum += t_n;
            println!(
                "{:?}-{:?}: t = {}\tn = {}\tt*n = {}",
                current,
                next,
                t,
                n,
                t_n
            );
            vec_tnp.push(t_n);
        }

        println!("Suma: {}", sum);

        for (indx, next) in ant.available.iter().enumerate() {
            let prob = vec_tnp[indx] / sum;
            println!("{:?}-{:?}: prob = {}", current, next, prob);
            vec_tnp[indx] = prob;
        }

        let mut rng = thread_rng();
        let num = rng.gen::<f64>();
        let mut s = 0.0;
        let mut next_indx = 0;
        for (i, &prob) in vec_tnp.iter().enumerate() {
            s += prob;
            if num < s {
                next_indx = i;
                break;
            }
        }

        println!("Numero aleatorio para la Probabilidad: {}", num);

        ant.available[next_indx].clone()
    }

    fn get_path_cost(&self, path: &[Node]) -> f32 {
        let mut dist = 0.0;
        for i in 1..path.len() {
            dist += self.distance[path[i - 1].clone() as usize][path[i].clone() as usize];
        }
        dist
    }

    fn update_pheromone(&mut self, vec_paths: Vec<(&Vec<Node>, f32)>) {
        for i in 0..N_NODES {
            for j in 0..N_NODES {
                if i != j {
                    self.pheromone[i][j] = self.pheromone[i][j] * self.rho;
                    print!(
                        "{:?}-{:?}: Feromona = {}",
                        AVAIL_NODES[i],
                        AVAIL_NODES[j],
                        self.pheromone[i][j]
                    );
                    for &(path, cost) in &vec_paths {
                        // let f_x = self.pheromone[i][j] * self.rho;
                        let mut f_x = 0.0;
                        for x in 1..path.len() {
                            if path[x] == AVAIL_NODES[i] {
                                if path[x - 1] == AVAIL_NODES[j] {
                                    f_x = 1.0 / cost;
                                }
                            } else if path[x] == AVAIL_NODES[j] {
                                if path[x - 1] == AVAIL_NODES[i] {
                                    f_x = 1.0 / cost;
                                }
                            }
                        }
                        print!(" + {}", f_x);
                        self.pheromone[i][j] += f_x as f64;
                    }
                    println!(" = {}", self.pheromone[i][j]);
                }
            }
        }
    }

    fn ant_iteration(&mut self) {
        // print_matrix(&SCORES, "Matriz Distancia");
        // print_matrix(&self.visibility, "Matriz Visibilidad");
        // print_matrix(&self.pheromone, "Matriz Feromona");
        let mut best_global_ant: (Vec<Node>, f32) = (Vec::new(), 100000000.0);
        for iter in 0..self.num_it {
            println!("\nIteración {}", iter +1 );
            println!("Matriz Distancia\n{:?}", &self.distance);
            println!("Matriz Visibilidad\n{:?}", &self.visibility);
            println!("Matriz Feromona\n{:?}", &self.pheromone);

            let mut best_iter_ant: (Vec<Node>, f32) = (Vec::new(), 100000000.0);

            let mut vec_ants = Vec::new();
            for i in 0..self.num_ant {
                println!("Hormiga {}", i + 1);
                let start_node = E;
                let mut ant = Ant::new(&start_node);
                println!("Ciudad inicial: {:?}", start_node);
                for _ in 0..N_NODES - 1 {
                    let next = self.compute_next_node(&ant);
                    println!("Ciudad Siguiente: {:?}\n", next);
                    ant.memory.push(next);
                    self.compute_available_nodes(&mut ant);
                }
                println!("Hormiga {}: {:?}\n", i + 1, ant.memory);
                vec_ants.push(ant.memory);
            }

            let mut tupl_vec = Vec::new();
            for (indx, ant) in vec_ants.iter().enumerate() {
                let cost = self.get_path_cost(ant);
                println!(
                    "Hormiga {} {:?} - Costo: {}",
                    indx + 1,
                    ant,
                    cost
                );
                if cost < best_iter_ant.1 {
                    best_iter_ant.0 = ant.clone();
                    best_iter_ant.1 = cost;
                }
                if cost < best_global_ant.1 {
                    best_global_ant.0 = ant.clone();
                    best_global_ant.1 = cost;
                }
                tupl_vec.push((ant, cost));
            }
            println!("----------\nMejor Hormiga Iteración {}: {:?} - Costo: {}\n----------", iter + 1, best_iter_ant.0, best_iter_ant.1);

            self.update_pheromone(tupl_vec);
        }

        println!("----------\nMejor Hormiga Global: {:?} - Costo: {}\n----------", best_global_ant.0, best_global_ant.1);
    }
}

fn main() {
    let mut colony = AntColony::new(0.99, 1.0, 1.0, 1, 0.1, 3, 1);
    colony.ant_iteration();
}
<|endoftext|>


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

//! write docs here

use std::task::spawn;
use std::comm::channel;

/// write docs here
pub type WorkUnit<ARG, RV> = (ARG, Sender<RV>);

/// write docs here
pub enum MessageToWorker<ARG, RV> {
    /// A work unit.
    Work(WorkUnit<ARG, RV>),
    /// Shut down the worker task.
    Halt,
}

/// write docs here
pub enum MessageToDispatcher<ARG, RV> {
    /// A work unit that needs to be dispatched to a worker task.
    Dispatch(WorkUnit<ARG, RV>),
    /// Halt all worker tasks.
    HaltAll,
    /// Register a new worker task.
    RegisterWorker(Sender<Sender<Sender<MessageToWorker<ARG, RV>>>>),
}

/// A queue that distributes work items to worker tasks.
pub struct WorkQueue<ARG, RV> {
    /// write docs here
    dispatcher: Sender<MessageToDispatcher<ARG, RV>>,
}

/// A proxy to a `WorkQueue`. It can be freely cloned to use from multiple tasks.
pub struct WorkQueueProxy<ARG, RV> {
    /// write docs here
    dispatcher: Sender<MessageToDispatcher<ARG, RV>>,
}

/// A worker that executes tasks from its parent queue.
pub struct Worker<ARG, RV> {
    priv ask_for_work: Sender<Sender<MessageToWorker<ARG, RV>>>,
}

impl<ARG:Send, RV:Send> WorkQueue<ARG, RV> {
    /// Create a new work queue.
    pub fn create() -> WorkQueue<ARG, RV> {
        let (dispatcher, dispatcher_inbox) = channel::<MessageToDispatcher<ARG, RV>>();
        spawn(proc() {
            let (want_work, idle_worker) = channel::<Sender<MessageToWorker<ARG, RV>>>();
            let mut worker_count = 0;
            let inbox = dispatcher_inbox;
            let idle_worker = idle_worker;
            loop {
                match inbox.recv() {
                    Dispatch(work_item) => {
                        idle_worker.recv().send(Work(work_item));
                    },
                    RegisterWorker(want_idle_sender) => {
                        worker_count += 1;
                        want_idle_sender.send(want_work.clone());
                    }
                    HaltAll => {
                        while worker_count > 0 {
                            idle_worker.recv().send(Halt);
                            worker_count -= 1;
                        }
                        return;
                    },
                };
            }
        });
        return WorkQueue{dispatcher: dispatcher};
    }

    /// Create a copyable proxy that can be used to push work units.
    pub fn proxy(&self) -> WorkQueueProxy<ARG, RV> {
        return WorkQueueProxy{dispatcher: self.dispatcher.clone()};
    }

    /// Register a new worker. It will receive a sender where it can ask for tasks.
    pub fn register_worker(&self) -> Sender<Sender<MessageToWorker<ARG, RV>>> {
        let (reg_s, reg_r) = channel::<Sender<Sender<MessageToWorker<ARG, RV>>>>();
        self.dispatcher.send(RegisterWorker(reg_s));
        return reg_r.recv();
    }

    /// Create a new worker.
    pub fn worker(&self) -> Worker<ARG, RV> {
        return Worker{ask_for_work: self.register_worker()};
    }

    /// Push a work item to this queue.
    pub fn push(&self, arg: ARG) -> Receiver<RV> {
        let (rv, wait_for_rv) = channel::<RV>();
        self.dispatcher.send(Dispatch((arg, rv)));
        return wait_for_rv;
    }
}

// rustc complais "cannot implement a destructor on a structure with
// type parameters", but our destruction is safe, we only send
// a simple message on a channel.
#[unsafe_destructor]
impl<ARG:Send, RV:Send> Drop for WorkQueue<ARG, RV> {
    fn drop(&mut self) {
        self.dispatcher.send(HaltAll);
    }
}

impl<ARG:Send, RV:Send> WorkQueueProxy<ARG, RV> {
    /// Push a work item to this queue.
    pub fn push(&self, arg: ARG) -> Receiver<RV> {
        let (rv, wait_for_rv) = channel::<RV>();
        self.dispatcher.send(Dispatch((arg, rv)));
        return wait_for_rv;
    }
}

impl<ARG:Send, RV:Send> Clone for WorkQueueProxy<ARG, RV> {
    fn clone(&self) -> WorkQueueProxy<ARG, RV> {
        return WorkQueueProxy{dispatcher: self.dispatcher.clone()};
    }
}

impl<ARG:Send, RV:Send> Worker<ARG, RV> {
    pub fn run(&self, fun: |arg: ARG| -> RV) {
        loop {
            let (idle, work_unit) = channel::<MessageToWorker<ARG, RV>>();
            self.ask_for_work.send(idle);
            match work_unit.recv() {
                Work((arg, rv)) => rv.send((fun)(arg)),
                Halt            => return
            };
        }
    }
}

#[cfg(test)]
fn spawn_test_worker(queue: &WorkQueue<int, int>) {
    let worker = queue.worker();
    spawn(proc() {
        worker.run(|arg| arg * 2);
    });
}

#[cfg(test)]
mod test {
    use std::task::spawn;
    use super::{WorkQueue, spawn_test_worker};

    #[test]
    fn test_queue() {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 3) {
            spawn_test_worker(&queue);
        }

        let return_list: ~[int] =
            range(0, 10)
            .map(|c| queue.push(c))
            .map(|rv| rv.recv())
            .collect();

        assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
    }

    #[test]
    fn test_enqueue_from_tasks() {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 3) {
            spawn_test_worker(&queue);
        }
        let mut promise_list: ~[Receiver<int>] = ~[];
        let queue_proxy = queue.proxy();
        for c in range(0, 10) {
            let queue_proxy_clone = queue_proxy.clone();
            let (done, promise) = channel::<int>();
            promise_list.push(promise);
            spawn(proc() {
                let done = done;
                let queue = queue_proxy_clone;
                let rv = queue.push(c);
                done.send(rv.recv());
            });
        }

        let return_list: ~[int] =
            promise_list
            .iter()
            .map(|promise| promise.recv())
            .collect();
        assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
    }
}

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

    use self::test::BenchHarness;
    use super::{WorkQueue, spawn_test_worker};

    #[bench]
    fn bench_50_tasks_4_threads(b: &mut BenchHarness) {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 4) {
            spawn_test_worker(&queue);
        }
        b.iter(|| {
            let _: ~[int] =
                range(0, 50)
                .map(|_| queue.push(1))
                .map(|rv| rv.recv())
                .collect();
        });
    }

    #[bench]
    fn bench_spawn_5_workers(b: &mut BenchHarness) {
        b.iter(|| {
            let queue = WorkQueue::<int, int>::create();
            for _ in range(0, 5) {
                spawn_test_worker(&queue);
            }
        });
    }
}
<commit_msg>inline spawn_test_worker code<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.

//! write docs here

use std::task::spawn;
use std::comm::channel;

/// write docs here
pub type WorkUnit<ARG, RV> = (ARG, Sender<RV>);

/// write docs here
pub enum MessageToWorker<ARG, RV> {
    /// A work unit.
    Work(WorkUnit<ARG, RV>),
    /// Shut down the worker task.
    Halt,
}

/// write docs here
pub enum MessageToDispatcher<ARG, RV> {
    /// A work unit that needs to be dispatched to a worker task.
    Dispatch(WorkUnit<ARG, RV>),
    /// Halt all worker tasks.
    HaltAll,
    /// Register a new worker task.
    RegisterWorker(Sender<Sender<Sender<MessageToWorker<ARG, RV>>>>),
}

/// A queue that distributes work items to worker tasks.
pub struct WorkQueue<ARG, RV> {
    /// write docs here
    dispatcher: Sender<MessageToDispatcher<ARG, RV>>,
}

/// A proxy to a `WorkQueue`. It can be freely cloned to use from multiple tasks.
pub struct WorkQueueProxy<ARG, RV> {
    /// write docs here
    dispatcher: Sender<MessageToDispatcher<ARG, RV>>,
}

/// A worker that executes tasks from its parent queue.
pub struct Worker<ARG, RV> {
    priv ask_for_work: Sender<Sender<MessageToWorker<ARG, RV>>>,
}

impl<ARG:Send, RV:Send> WorkQueue<ARG, RV> {
    /// Create a new work queue.
    pub fn create() -> WorkQueue<ARG, RV> {
        let (dispatcher, dispatcher_inbox) = channel::<MessageToDispatcher<ARG, RV>>();
        spawn(proc() {
            let (want_work, idle_worker) = channel::<Sender<MessageToWorker<ARG, RV>>>();
            let mut worker_count = 0;
            let inbox = dispatcher_inbox;
            let idle_worker = idle_worker;
            loop {
                match inbox.recv() {
                    Dispatch(work_item) => {
                        idle_worker.recv().send(Work(work_item));
                    },
                    RegisterWorker(want_idle_sender) => {
                        worker_count += 1;
                        want_idle_sender.send(want_work.clone());
                    }
                    HaltAll => {
                        while worker_count > 0 {
                            idle_worker.recv().send(Halt);
                            worker_count -= 1;
                        }
                        return;
                    },
                };
            }
        });
        return WorkQueue{dispatcher: dispatcher};
    }

    /// Create a copyable proxy that can be used to push work units.
    pub fn proxy(&self) -> WorkQueueProxy<ARG, RV> {
        return WorkQueueProxy{dispatcher: self.dispatcher.clone()};
    }

    /// Register a new worker. It will receive a sender where it can ask for tasks.
    pub fn register_worker(&self) -> Sender<Sender<MessageToWorker<ARG, RV>>> {
        let (reg_s, reg_r) = channel::<Sender<Sender<MessageToWorker<ARG, RV>>>>();
        self.dispatcher.send(RegisterWorker(reg_s));
        return reg_r.recv();
    }

    /// Create a new worker.
    pub fn worker(&self) -> Worker<ARG, RV> {
        return Worker{ask_for_work: self.register_worker()};
    }

    /// Push a work item to this queue.
    pub fn push(&self, arg: ARG) -> Receiver<RV> {
        let (rv, wait_for_rv) = channel::<RV>();
        self.dispatcher.send(Dispatch((arg, rv)));
        return wait_for_rv;
    }
}

// rustc complais "cannot implement a destructor on a structure with
// type parameters", but our destruction is safe, we only send
// a simple message on a channel.
#[unsafe_destructor]
impl<ARG:Send, RV:Send> Drop for WorkQueue<ARG, RV> {
    fn drop(&mut self) {
        self.dispatcher.send(HaltAll);
    }
}

impl<ARG:Send, RV:Send> WorkQueueProxy<ARG, RV> {
    /// Push a work item to this queue.
    pub fn push(&self, arg: ARG) -> Receiver<RV> {
        let (rv, wait_for_rv) = channel::<RV>();
        self.dispatcher.send(Dispatch((arg, rv)));
        return wait_for_rv;
    }
}

impl<ARG:Send, RV:Send> Clone for WorkQueueProxy<ARG, RV> {
    fn clone(&self) -> WorkQueueProxy<ARG, RV> {
        return WorkQueueProxy{dispatcher: self.dispatcher.clone()};
    }
}

impl<ARG:Send, RV:Send> Worker<ARG, RV> {
    pub fn run(&self, fun: |arg: ARG| -> RV) {
        loop {
            let (idle, work_unit) = channel::<MessageToWorker<ARG, RV>>();
            self.ask_for_work.send(idle);
            match work_unit.recv() {
                Work((arg, rv)) => rv.send((fun)(arg)),
                Halt            => return
            };
        }
    }
}

#[cfg(test)]
mod test {
    use std::task::spawn;
    use super::WorkQueue;

    #[test]
    fn test_queue() {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 3) {
            let worker = queue.worker();
            spawn(proc() { worker.run(|arg| arg * 2); });
        }

        let return_list: ~[int] =
            range(0, 10)
            .map(|c| queue.push(c))
            .map(|rv| rv.recv())
            .collect();

        assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
    }

    #[test]
    fn test_enqueue_from_tasks() {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 3) {
            let worker = queue.worker();
            spawn(proc() { worker.run(|arg| arg * 2); });
        }
        let mut promise_list: ~[Receiver<int>] = ~[];
        let queue_proxy = queue.proxy();
        for c in range(0, 10) {
            let queue_proxy_clone = queue_proxy.clone();
            let (done, promise) = channel::<int>();
            promise_list.push(promise);
            spawn(proc() {
                let done = done;
                let queue = queue_proxy_clone;
                let rv = queue.push(c);
                done.send(rv.recv());
            });
        }

        let return_list: ~[int] =
            promise_list
            .iter()
            .map(|promise| promise.recv())
            .collect();
        assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
    }
}

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

    use self::test::BenchHarness;
    use super::WorkQueue;

    #[bench]
    fn bench_50_tasks_4_threads(b: &mut BenchHarness) {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 4) {
            let worker = queue.worker();
            spawn(proc() { worker.run(|arg| arg * 2); });
        }
        b.iter(|| {
            let _: ~[int] =
                range(0, 50)
                .map(|_| queue.push(1))
                .map(|rv| rv.recv())
                .collect();
        });
    }

    #[bench]
    fn bench_spawn_5_workers(b: &mut BenchHarness) {
        b.iter(|| {
            let queue = WorkQueue::<int, int>::create();
            for _ in range(0, 5) {
                let worker = queue.worker();
                spawn(proc() { worker.run(|arg| arg * 2); });
            }
        });
    }
}
<|endoftext|>


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

//! write docs here

use std::task;
use std::comm::channel;

/// write docs here
pub struct WorkUnit<ARG, RV> {
    /// Argument that will be passed to the worker.
    arg: ARG,
    /// Sender end of a channel. Worker will send its return value here.
    rv: Sender<RV>,
}

/// write docs here
pub enum MessageToWorker<ARG, RV> {
    /// A work unit.
    Work(WorkUnit<ARG, RV>),
    /// Shut down the worker task.
    Halt,
}

/// write docs here
pub enum MessageToDispatcher<ARG, RV> {
    /// A work unit that needs to be dispatched to a worker task.
    Dispatch(WorkUnit<ARG, RV>),
    /// Halt all worker tasks.
    HaltAll,
    /// Register a new worker task.
    RegisterWorker(Sender<Sender<Sender<MessageToWorker<ARG, RV>>>>),
}

/// A queue that distributes work items to worker tasks.
pub struct WorkQueue<ARG, RV> {
    /// write docs here
    dispatcher: Sender<MessageToDispatcher<ARG, RV>>,
}

/// A proxy to a `WorkQueue`. It can be freely cloned to use from multiple tasks.
pub struct WorkQueueProxy<ARG, RV> {
    /// write docs here
    dispatcher: Sender<MessageToDispatcher<ARG, RV>>,
}

impl<ARG:Send, RV:Send> WorkQueue<ARG, RV> {
    /// Create a new work queue.
    pub fn create() -> WorkQueue<ARG, RV> {
        let (dispatcher, dispatcher_inbox) = channel::<MessageToDispatcher<ARG, RV>>();
        task::spawn(proc() {
            let (want_work, idle_worker) = channel::<Sender<MessageToWorker<ARG, RV>>>();
            let mut worker_count = 0;
            let inbox = dispatcher_inbox;
            let idle_worker = idle_worker;
            loop {
                match inbox.recv() {
                    Dispatch(work_item) => {
                        idle_worker.recv().send(Work(work_item));
                    },
                    RegisterWorker(want_idle_sender) => {
                        worker_count += 1;
                        want_idle_sender.send(want_work.clone());
                    }
                    HaltAll => {
                        while worker_count > 0 {
                            idle_worker.recv().send(Halt);
                            worker_count -= 1;
                        }
                        return;
                    },
                };
            }
        });
        return WorkQueue{dispatcher: dispatcher};
    }

    /// Create a copyable proxy that can be used to push work units.
    pub fn proxy(&self) -> WorkQueueProxy<ARG, RV> {
        return WorkQueueProxy{dispatcher: self.dispatcher.clone()};
    }

    /// Register a new worker. It will receive a sender where it can ask for tasks.
    pub fn register_worker(&self) -> Sender<Sender<MessageToWorker<ARG, RV>>> {
        let (reg_s, reg_r) = channel::<Sender<Sender<MessageToWorker<ARG, RV>>>>();
        self.dispatcher.send(RegisterWorker(reg_s));
        return reg_r.recv();
    }

    /// Push a work item to this queue.
    pub fn push(&self, arg: ARG) -> Receiver<RV> {
        let (rv, wait_for_rv) = channel::<RV>();
        self.dispatcher.send(Dispatch(WorkUnit{arg: arg, rv: rv}));
        return wait_for_rv;
    }
}

// rustc complais "cannot implement a destructor on a structure with
// type parameters", but our destruction is safe, we only send
// a simple message on a channel.
#[unsafe_destructor]
impl<ARG:Send, RV:Send> Drop for WorkQueue<ARG, RV> {
    fn drop(&mut self) {
        self.dispatcher.send(HaltAll);
    }
}

impl<ARG:Send, RV:Send> WorkQueueProxy<ARG, RV> {
    /// Push a work item to this queue.
    pub fn push(&self, arg: ARG) -> Receiver<RV> {
        let (rv, wait_for_rv) = channel::<RV>();
        self.dispatcher.send(Dispatch(WorkUnit{arg: arg, rv: rv}));
        return wait_for_rv;
    }
}

impl<ARG:Send, RV:Send> Clone for WorkQueueProxy<ARG, RV> {
    fn clone(&self) -> WorkQueueProxy<ARG, RV> {
        return WorkQueueProxy{dispatcher: self.dispatcher.clone()};
    }
}

#[cfg(test)]
fn spawn_test_worker(queue: &WorkQueue<int, int>) {
    let want_work = queue.register_worker();
    task::spawn(proc() {
        let want_work = want_work;
        loop {
            let (idle, get_work_unit) = channel::<MessageToWorker<int, int>>();
            want_work.send(idle);
            let work_unit = match get_work_unit.recv() {
                Work(wu) => wu,
                Halt     => return
            };
            let rv = work_unit.arg * 2;
            work_unit.rv.send(rv);
        }
    });
}

#[cfg(test)]
mod test {
    use std::task;
    use super::{WorkQueue, spawn_test_worker};

    #[test]
    fn test_queue() {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 3) {
            spawn_test_worker(&queue);
        }

        let return_list: ~[int] =
            range(0, 10)
            .map(|c| queue.push(c))
            .map(|rv| rv.recv())
            .collect();

        assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
    }

    #[test]
    fn test_enqueue_from_tasks() {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 3) {
            spawn_test_worker(&queue);
        }
        let mut promise_list: ~[Receiver<int>] = ~[];
        let queue_proxy = queue.proxy();
        for c in range(0, 10) {
            let queue_proxy_clone = queue_proxy.clone();
            let (done, promise) = channel::<int>();
            promise_list.push(promise);
            task::spawn(proc() {
                let done = done;
                let queue = queue_proxy_clone;
                let rv = queue.push(c);
                done.send(rv.recv());
            });
        }

        let return_list: ~[int] =
            promise_list
            .iter()
            .map(|promise| promise.recv())
            .collect();
        assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
    }
}

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

    use self::test::BenchHarness;
    use super::{WorkQueue, spawn_test_worker};

    #[bench]
    fn bench_50_tasks_4_threads(b: &mut BenchHarness) {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 4) {
            spawn_test_worker(&queue);
        }
        b.iter(|| {
            let _: ~[int] =
                range(0, 50)
                .map(|_| queue.push(1))
                .map(|rv| rv.recv())
                .collect();
        });
    }

    #[bench]
    fn bench_spawn_5_workers(b: &mut BenchHarness) {
        b.iter(|| {
            let queue = WorkQueue::<int, int>::create();
            for _ in range(0, 5) {
                spawn_test_worker(&queue);
            }
        });
    }
}
<commit_msg>transform WorkUnit to a tuple<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.

//! write docs here

use std::task;
use std::comm::channel;

/// write docs here
pub type WorkUnit<ARG, RV> = (ARG, Sender<RV>);

/// write docs here
pub enum MessageToWorker<ARG, RV> {
    /// A work unit.
    Work(WorkUnit<ARG, RV>),
    /// Shut down the worker task.
    Halt,
}

/// write docs here
pub enum MessageToDispatcher<ARG, RV> {
    /// A work unit that needs to be dispatched to a worker task.
    Dispatch(WorkUnit<ARG, RV>),
    /// Halt all worker tasks.
    HaltAll,
    /// Register a new worker task.
    RegisterWorker(Sender<Sender<Sender<MessageToWorker<ARG, RV>>>>),
}

/// A queue that distributes work items to worker tasks.
pub struct WorkQueue<ARG, RV> {
    /// write docs here
    dispatcher: Sender<MessageToDispatcher<ARG, RV>>,
}

/// A proxy to a `WorkQueue`. It can be freely cloned to use from multiple tasks.
pub struct WorkQueueProxy<ARG, RV> {
    /// write docs here
    dispatcher: Sender<MessageToDispatcher<ARG, RV>>,
}

impl<ARG:Send, RV:Send> WorkQueue<ARG, RV> {
    /// Create a new work queue.
    pub fn create() -> WorkQueue<ARG, RV> {
        let (dispatcher, dispatcher_inbox) = channel::<MessageToDispatcher<ARG, RV>>();
        task::spawn(proc() {
            let (want_work, idle_worker) = channel::<Sender<MessageToWorker<ARG, RV>>>();
            let mut worker_count = 0;
            let inbox = dispatcher_inbox;
            let idle_worker = idle_worker;
            loop {
                match inbox.recv() {
                    Dispatch(work_item) => {
                        idle_worker.recv().send(Work(work_item));
                    },
                    RegisterWorker(want_idle_sender) => {
                        worker_count += 1;
                        want_idle_sender.send(want_work.clone());
                    }
                    HaltAll => {
                        while worker_count > 0 {
                            idle_worker.recv().send(Halt);
                            worker_count -= 1;
                        }
                        return;
                    },
                };
            }
        });
        return WorkQueue{dispatcher: dispatcher};
    }

    /// Create a copyable proxy that can be used to push work units.
    pub fn proxy(&self) -> WorkQueueProxy<ARG, RV> {
        return WorkQueueProxy{dispatcher: self.dispatcher.clone()};
    }

    /// Register a new worker. It will receive a sender where it can ask for tasks.
    pub fn register_worker(&self) -> Sender<Sender<MessageToWorker<ARG, RV>>> {
        let (reg_s, reg_r) = channel::<Sender<Sender<MessageToWorker<ARG, RV>>>>();
        self.dispatcher.send(RegisterWorker(reg_s));
        return reg_r.recv();
    }

    /// Push a work item to this queue.
    pub fn push(&self, arg: ARG) -> Receiver<RV> {
        let (rv, wait_for_rv) = channel::<RV>();
        self.dispatcher.send(Dispatch((arg, rv)));
        return wait_for_rv;
    }
}

// rustc complais "cannot implement a destructor on a structure with
// type parameters", but our destruction is safe, we only send
// a simple message on a channel.
#[unsafe_destructor]
impl<ARG:Send, RV:Send> Drop for WorkQueue<ARG, RV> {
    fn drop(&mut self) {
        self.dispatcher.send(HaltAll);
    }
}

impl<ARG:Send, RV:Send> WorkQueueProxy<ARG, RV> {
    /// Push a work item to this queue.
    pub fn push(&self, arg: ARG) -> Receiver<RV> {
        let (rv, wait_for_rv) = channel::<RV>();
        self.dispatcher.send(Dispatch((arg, rv)));
        return wait_for_rv;
    }
}

impl<ARG:Send, RV:Send> Clone for WorkQueueProxy<ARG, RV> {
    fn clone(&self) -> WorkQueueProxy<ARG, RV> {
        return WorkQueueProxy{dispatcher: self.dispatcher.clone()};
    }
}

#[cfg(test)]
fn spawn_test_worker(queue: &WorkQueue<int, int>) {
    let want_work = queue.register_worker();
    task::spawn(proc() {
        let want_work = want_work;
        loop {
            let (idle, get_work_unit) = channel::<MessageToWorker<int, int>>();
            want_work.send(idle);
            let (arg, rv) = match get_work_unit.recv() {
                Work((arg, rv)) => (arg, rv),
                Halt            => return
            };
            rv.send(arg * 2);
        }
    });
}

#[cfg(test)]
mod test {
    use std::task;
    use super::{WorkQueue, spawn_test_worker};

    #[test]
    fn test_queue() {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 3) {
            spawn_test_worker(&queue);
        }

        let return_list: ~[int] =
            range(0, 10)
            .map(|c| queue.push(c))
            .map(|rv| rv.recv())
            .collect();

        assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
    }

    #[test]
    fn test_enqueue_from_tasks() {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 3) {
            spawn_test_worker(&queue);
        }
        let mut promise_list: ~[Receiver<int>] = ~[];
        let queue_proxy = queue.proxy();
        for c in range(0, 10) {
            let queue_proxy_clone = queue_proxy.clone();
            let (done, promise) = channel::<int>();
            promise_list.push(promise);
            task::spawn(proc() {
                let done = done;
                let queue = queue_proxy_clone;
                let rv = queue.push(c);
                done.send(rv.recv());
            });
        }

        let return_list: ~[int] =
            promise_list
            .iter()
            .map(|promise| promise.recv())
            .collect();
        assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
    }
}

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

    use self::test::BenchHarness;
    use super::{WorkQueue, spawn_test_worker};

    #[bench]
    fn bench_50_tasks_4_threads(b: &mut BenchHarness) {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 4) {
            spawn_test_worker(&queue);
        }
        b.iter(|| {
            let _: ~[int] =
                range(0, 50)
                .map(|_| queue.push(1))
                .map(|rv| rv.recv())
                .collect();
        });
    }

    #[bench]
    fn bench_spawn_5_workers(b: &mut BenchHarness) {
        b.iter(|| {
            let queue = WorkQueue::<int, int>::create();
            for _ in range(0, 5) {
                spawn_test_worker(&queue);
            }
        });
    }
}
<|endoftext|>