<commit_before>/// # Even Fibonacci numbers
/// ## Problem 2
/// Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
/// 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
/// By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

extern crate num;

use std::mem;

struct Fib {
    a: int,
    b: int,
}

impl Iterator<int> for Fib {
    fn next(&mut self) -> Option<int> {
        let new_b = self.a + self.b;
        let new_a = mem::replace(&mut self.b, new_b);

        Some(mem::replace(&mut self.a, new_a))
    }
}

fn main() {
    let fib = Fib {a: 1i, b: 2i};
    let mut total = 0;

    for n in fib.take_while(|&n| n <= 4000000) {
        if n % 2 == 0 {
            total +=n;
        }
    }

    println!("Result: {}", total);
}
<commit_msg>Rust: Problem 2 - Refactor to functional<commit_after>/// # Even Fibonacci numbers
/// ## Problem 2
/// Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
/// 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
/// By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

extern crate num;

use std::mem;
use std::iter::AdditiveIterator;

struct Fib {
    a: int,
    b: int,
}

impl Iterator<int> for Fib {
    fn next(&mut self) -> Option<int> {
        let new_b = self.a + self.b;
        let new_a = mem::replace(&mut self.b, new_b);

        Some(mem::replace(&mut self.a, new_a))
    }
}

fn main() {
    let fib = Fib {a: 1i, b: 2i};
    let total = fib.take_while(|&n| n <= 4000000).filter(|n| n % 2 == 0).sum();

    println!("Result: {}", total);
}
<|endoftext|>


<commit_before>use std::{
    io,
    sync::{
        atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering},
        Arc,
    },
    time::{Duration, Instant},
};

use crate::{
    config::ServerConfig,
    context::SharedContext,
    relay::{loadbalancing::server::LoadBalancer, socks5::Address, tcprelay::client::ServerClient},
};

use futures::{Future, Stream};
use log::{debug, error, info};
use tokio::{
    self,
    timer::{Interval, Timeout},
};

struct Server {
    config: Arc<ServerConfig>,
    elapsed: AtomicU64,
    available: AtomicBool,
}

impl Server {
    fn new(config: ServerConfig) -> Server {
        Server {
            config: Arc::new(config),
            elapsed: AtomicU64::new(0),
            available: AtomicBool::new(true),
        }
    }

    fn is_available(&self) -> bool {
        self.available.load(Ordering::Acquire)
    }

    fn delay(&self) -> u64 {
        self.elapsed.load(Ordering::Acquire)
    }
}

const DEFAULT_CHECK_INTERVAL_SEC: u64 = 10;

struct Inner {
    servers: Vec<Arc<Server>>,
    best_idx: AtomicUsize,
}

impl Inner {
    fn new(context: SharedContext) -> Inner {
        let config = context.config();

        if config.server.is_empty() {
            panic!("no servers");
        }

        let check_required = config.server.len() > 1;

        let mut servers = Vec::new();
        for svr in &config.server {
            let sc = Arc::new(Server::new(svr.clone()));
            servers.push(sc.clone());

            if !check_required {
                continue;
            }

            let addr = Address::DomainNameAddress("www.example.com".to_owned(), 80);
            let context = context.clone();

            tokio::spawn(
                // Check every 10 seconds
                Interval::new(
                    Instant::now() + Duration::from_secs(1),
                    Duration::from_secs(DEFAULT_CHECK_INTERVAL_SEC),
                )
                .for_each(move |_| {
                    let sc = sc.clone();

                    let fut1 = Inner::check_delay(sc.clone(), context.clone(), addr.clone());
                    let fut2 = Inner::check_delay(sc.clone(), context.clone(), addr.clone());
                    let fut3 = Inner::check_delay(sc.clone(), context.clone(), addr.clone());

                    fut1.join3(fut2, fut3).then(move |res| {
                        match res {
                            Ok((d1, d2, d3)) => {
                                sc.available.store(true, Ordering::Release);
                                sc.elapsed.store((d1 + d2 + d3) / 3, Ordering::Release);
                            }
                            Err(..) => {
                                sc.available.store(false, Ordering::Release);
                            }
                        }

                        Ok(())
                    })
                })
                .map_err(|_| ()),
            );
        }

        Inner {
            servers,
            best_idx: AtomicUsize::new(0),
        }
    }

    fn check_delay(
        sc: Arc<Server>,
        context: SharedContext,
        addr: Address,
    ) -> impl Future<Item = u64, Error = io::Error> {
        let start = Instant::now();
        let fut = ServerClient::connect(context, addr, sc.config.clone());
        Timeout::new(fut, Duration::from_secs(5)).then(move |res| {
            let elapsed = Instant::now() - start;
            let elapsed = elapsed.as_secs() * 1000 + u64::from(elapsed.subsec_millis()); // Converted to ms
            match res {
                Ok(..) => {
                    // Connected ... record its time
                    debug!(
                        "checked remote server {} connected with {} ms",
                        sc.config.addr(),
                        elapsed
                    );
                    Ok(elapsed)
                }
                Err(err) => {
                    match err.into_inner() {
                        Some(err) => {
                            error!("failed to check server {}, error: {}", sc.config.addr(), err);

                            // NOTE: connection / handshake error, server is down
                            Err(err)
                        }
                        None => {
                            // Timeout
                            error!("checked remote server {} connect timeout", sc.config.addr());

                            // NOTE: timeout is still available, but server is too slow
                            Ok(elapsed)
                        }
                    }
                }
            }
        })
    }

    fn best_idx(&self) -> usize {
        self.best_idx.load(Ordering::Acquire)
    }

    fn set_best_idx(&self, idx: usize) {
        self.best_idx.store(idx, Ordering::Release)
    }

    fn best_server(&self) -> &Arc<Server> {
        &self.servers[self.best_idx()]
    }
}

#[derive(Clone)]
pub struct PingBalancer {
    inner: Arc<Inner>,
}

impl PingBalancer {
    pub fn new(context: SharedContext) -> PingBalancer {
        let inner = Arc::new(Inner::new(context));

        let inner_cloned = inner.clone();
        tokio::spawn(
            Interval::new(
                Instant::now() + Duration::from_secs(2),
                Duration::from_secs(DEFAULT_CHECK_INTERVAL_SEC),
            )
            .for_each(move |_| {
                let inner = inner_cloned.clone();

                if inner.servers.is_empty() {
                    panic!("No server");
                }

                // Choose the best one
                let mut svr_idx = 0;

                for (idx, svr) in inner.servers.iter().enumerate() {
                    let choosen_svr = &inner.servers[svr_idx];
                    if svr.is_available() && (!choosen_svr.is_available() || svr.delay() < choosen_svr.delay()) {
                        svr_idx = idx;
                    }
                }

                let choosen_svr = &inner.servers[svr_idx];
                if svr_idx == 0 && !choosen_svr.is_available() {
                    // Cannot find any usable servers, use the first one (svr_idx = 0)
                    error!(
                        "cannot find any usable servers, picked {} delay {} ms",
                        choosen_svr.config.addr(),
                        choosen_svr.delay()
                    );
                } else {
                    debug!(
                        "chosen the best server {} delay {} ms",
                        choosen_svr.config.addr(),
                        choosen_svr.delay()
                    );
                }

                if inner.best_idx() != svr_idx {
                    info!(
                        "switched server from {} to {}",
                        inner.best_server().config.addr(),
                        choosen_svr.config.addr()
                    );
                }

                inner.set_best_idx(svr_idx);

                Ok(())
            })
            .map_err(|_| ()),
        );

        PingBalancer { inner }
    }
}

impl LoadBalancer for PingBalancer {
    fn pick_server(&mut self) -> Arc<ServerConfig> {
        if self.inner.servers.is_empty() {
            panic!("no server in configuration");
        }
        self.inner.best_server().config.clone()
    }

    fn total(&self) -> usize {
        self.inner.servers.len()
    }
}
<commit_msg>Print delay in switch info<commit_after>use std::{
    io,
    sync::{
        atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering},
        Arc,
    },
    time::{Duration, Instant},
};

use crate::{
    config::ServerConfig,
    context::SharedContext,
    relay::{loadbalancing::server::LoadBalancer, socks5::Address, tcprelay::client::ServerClient},
};

use futures::{Future, Stream};
use log::{debug, error, info};
use tokio::{
    self,
    timer::{Interval, Timeout},
};

struct Server {
    config: Arc<ServerConfig>,
    elapsed: AtomicU64,
    available: AtomicBool,
}

impl Server {
    fn new(config: ServerConfig) -> Server {
        Server {
            config: Arc::new(config),
            elapsed: AtomicU64::new(0),
            available: AtomicBool::new(true),
        }
    }

    fn is_available(&self) -> bool {
        self.available.load(Ordering::Acquire)
    }

    fn delay(&self) -> u64 {
        self.elapsed.load(Ordering::Acquire)
    }
}

const DEFAULT_CHECK_INTERVAL_SEC: u64 = 10;

struct Inner {
    servers: Vec<Arc<Server>>,
    best_idx: AtomicUsize,
}

impl Inner {
    fn new(context: SharedContext) -> Inner {
        let config = context.config();

        if config.server.is_empty() {
            panic!("no servers");
        }

        let check_required = config.server.len() > 1;

        let mut servers = Vec::new();
        for svr in &config.server {
            let sc = Arc::new(Server::new(svr.clone()));
            servers.push(sc.clone());

            if !check_required {
                continue;
            }

            let addr = Address::DomainNameAddress("www.example.com".to_owned(), 80);
            let context = context.clone();

            tokio::spawn(
                // Check every 10 seconds
                Interval::new(
                    Instant::now() + Duration::from_secs(1),
                    Duration::from_secs(DEFAULT_CHECK_INTERVAL_SEC),
                )
                .for_each(move |_| {
                    let sc = sc.clone();

                    let fut1 = Inner::check_delay(sc.clone(), context.clone(), addr.clone());
                    let fut2 = Inner::check_delay(sc.clone(), context.clone(), addr.clone());
                    let fut3 = Inner::check_delay(sc.clone(), context.clone(), addr.clone());

                    fut1.join3(fut2, fut3).then(move |res| {
                        match res {
                            Ok((d1, d2, d3)) => {
                                sc.available.store(true, Ordering::Release);
                                sc.elapsed.store((d1 + d2 + d3) / 3, Ordering::Release);
                            }
                            Err(..) => {
                                sc.available.store(false, Ordering::Release);
                            }
                        }

                        Ok(())
                    })
                })
                .map_err(|_| ()),
            );
        }

        Inner {
            servers,
            best_idx: AtomicUsize::new(0),
        }
    }

    fn check_delay(
        sc: Arc<Server>,
        context: SharedContext,
        addr: Address,
    ) -> impl Future<Item = u64, Error = io::Error> {
        let start = Instant::now();
        let fut = ServerClient::connect(context, addr, sc.config.clone());
        Timeout::new(fut, Duration::from_secs(5)).then(move |res| {
            let elapsed = Instant::now() - start;
            let elapsed = elapsed.as_secs() * 1000 + u64::from(elapsed.subsec_millis()); // Converted to ms
            match res {
                Ok(..) => {
                    // Connected ... record its time
                    debug!(
                        "checked remote server {} connected with {} ms",
                        sc.config.addr(),
                        elapsed
                    );
                    Ok(elapsed)
                }
                Err(err) => {
                    match err.into_inner() {
                        Some(err) => {
                            error!("failed to check server {}, error: {}", sc.config.addr(), err);

                            // NOTE: connection / handshake error, server is down
                            Err(err)
                        }
                        None => {
                            // Timeout
                            error!(
                                "checked remote server {} connect timeout, elapsed {} ms",
                                sc.config.addr(),
                                elapsed
                            );

                            // NOTE: timeout is still available, but server is too slow
                            Ok(elapsed)
                        }
                    }
                }
            }
        })
    }

    fn best_idx(&self) -> usize {
        self.best_idx.load(Ordering::Acquire)
    }

    fn set_best_idx(&self, idx: usize) {
        self.best_idx.store(idx, Ordering::Release)
    }

    fn best_server(&self) -> &Arc<Server> {
        &self.servers[self.best_idx()]
    }
}

#[derive(Clone)]
pub struct PingBalancer {
    inner: Arc<Inner>,
}

impl PingBalancer {
    pub fn new(context: SharedContext) -> PingBalancer {
        let inner = Arc::new(Inner::new(context));

        let inner_cloned = inner.clone();
        tokio::spawn(
            Interval::new(
                Instant::now() + Duration::from_secs(2),
                Duration::from_secs(DEFAULT_CHECK_INTERVAL_SEC),
            )
            .for_each(move |_| {
                let inner = inner_cloned.clone();

                if inner.servers.is_empty() {
                    panic!("No server");
                }

                // Choose the best one
                let mut svr_idx = 0;

                for (idx, svr) in inner.servers.iter().enumerate() {
                    let choosen_svr = &inner.servers[svr_idx];
                    if svr.is_available() && (!choosen_svr.is_available() || svr.delay() < choosen_svr.delay()) {
                        svr_idx = idx;
                    }
                }

                let choosen_svr = &inner.servers[svr_idx];
                if svr_idx == 0 && !choosen_svr.is_available() {
                    // Cannot find any usable servers, use the first one (svr_idx = 0)
                    error!(
                        "cannot find any usable servers, picked {} (delay: {} ms)",
                        choosen_svr.config.addr(),
                        choosen_svr.delay()
                    );
                } else {
                    debug!(
                        "chosen the best server {} (delay: {} ms)",
                        choosen_svr.config.addr(),
                        choosen_svr.delay()
                    );
                }

                if inner.best_idx() != svr_idx {
                    info!(
                        "switched server from {} (delay: {} ms) to {} (delay: {} ms)",
                        inner.best_server().config.addr(),
                        inner.best_server().delay(),
                        choosen_svr.config.addr(),
                        choosen_svr.delay(),
                    );
                }

                inner.set_best_idx(svr_idx);

                Ok(())
            })
            .map_err(|_| ()),
        );

        PingBalancer { inner }
    }
}

impl LoadBalancer for PingBalancer {
    fn pick_server(&mut self) -> Arc<ServerConfig> {
        if self.inner.servers.is_empty() {
            panic!("no server in configuration");
        }
        self.inner.best_server().config.clone()
    }

    fn total(&self) -> usize {
        self.inner.servers.len()
    }
}
<|endoftext|>


<commit_before>use core::clone::Clone;

use alloc::boxed::*;

use common::memory::*;
use common::string::*;
use common::url::*;

use filesystems::unfs::*;

use programs::session::*;

pub struct HTTPScheme;

impl HTTPScheme {
    pub fn encode(text: String) -> String{
        let mut html = String::new();

        for c in text.chars() {
            match c {
                '&' => html = html + "&",
                '"' => html = html + """,
                '<' => html = html + "<",
                '>' => html = html + ">",
                _ => html = html + c
            }
        }

        return html;
    }
}

impl SessionModule for HTTPScheme {
    fn scheme(&self) -> String {
        return "http".to_string();
    }

    fn on_url(&mut self, session: &Session, url: &URL, callback: Box<FnBox(String)>){
        let mut path = String::new();

        for part in url.path.iter() {
            path = path + "/" + part.clone();
        }

        let mut html = "HTTP/1.1 200 OK\r\n".to_string()
                    + "Content-Type: text/html\r\n"
                    + "Connection: keep-alive\r\n"
                    + "\r\n";

        if path == "/files".to_string() {
            html = html + "<title>Files - Redox</title>\n";
        }else if path == "/readme".to_string() {
            html = html + "<title>Readme - Redox</title>\n";
        }else{
            html = html + "<title>Home - Redox</title>\n";
        }
        html = html + "<link rel='icon' href='data:;base64,iVBORw0KGgo='>\n";
        html = html + "<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css'>\n";
        html = html + "<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css'>\n";
        html = html + "\n";

        html = html + "
\n";
            html = html + "\n";
            html = html + "
\n";
            html = html + "
\n";
            html = html + "      <button type='button' class='navbar-toggle collapsed' data-toggle='collapse' data-target='#navbar-collapse'></button>\n";
            html = html + "      Redox Web Interface\n";
            html = html + "
\n";
            html = html + "
\n";
            html = html + "
\n";

            if path == "/readme".to_string() {
                html = html + "
Home
\n";
                html = html + "
Readme
\n";
            }else{
                html = html + "
Home
\n";
                html = html + "
Readme
\n";
            }

            html = html + "
\n";
            html = html + "
\n";
            html = html + "
\n";
            html = html + "\n";

            if path == "/readme".to_string() {
                unsafe {
                    html = html + "
\n";
                        let unfs = UnFS::new();
                        let readme_file = "README.md".to_string();
                        let readme_c_str = unfs.load(readme_file.clone());
                        if readme_c_str > 0 {
                            let readme = String::from_c_str(readme_c_str as *const u8);
                            unalloc(readme_c_str);

                            html = html + "
\n";
                                html = html + "
 " + readme_file.clone() + "
";
                            html = html + "
\n";

                            html = html + "
\n";
                                let mut in_code = false;
                                for line in readme.split("\n".to_string()){
                                    if line.starts_with("# ".to_string()){
                                        html = html + "
" + HTTPScheme::encode(line.substr(2, line.len() - 2)) + "
\n";
                                    }else if line.starts_with("## ".to_string()){
                                        html = html + "
" + HTTPScheme::encode(line.substr(3, line.len() - 3)) + "
\n";
                                    }else if line.starts_with("### ".to_string()){
                                        html = html + "
" + HTTPScheme::encode(line.substr(4, line.len() - 4)) + "
\n";
                                    }else if line.starts_with("- ".to_string()){
                                        html = html + "
" + HTTPScheme::encode(line.substr(2, line.len() - 2)) + "
\n";
                                    }else if line.starts_with("```".to_string()){
                                        if in_code {
                                            html = html + "</pre>\n";
                                            in_code = false;
                                        }else{
                                            html = html + "<pre>\n";
                                            in_code = true;
                                        }
                                    }else{
                                        html = html + HTTPScheme::encode(line);
                                        if in_code {
                                            html = html + "\n";
                                        }else{
                                            html = html + "<br/>\n";
                                        }
                                    }
                                }
                                if in_code {
                                    html = html + "</pre>\n";
                                }
                            html = html + "</div>\n";
                        }else{
                            html = html + "<div class='panel-heading'>\n";
                                html = html + "<h3 class='panel-title'><span class='glyphicon glyphicon-exlamation-sign'></span> Failed to open " + readme_file.clone() + "</h3>\n";
                            html = html + "</div>\n";
                        }
                    html = html + "</div>\n";
                }
            }else{
                let url_string = path.substr(1, path.len());
                if url_string.len() > 0 {
                    let url = URL::from_string(url_string);
                    let data = String::new(); //session.on_url(&url);
                    html = html + "<table class='table table-bordered'>\n";
                        html = html + "  <caption><h3>" + HTTPScheme::encode(url.to_string()) + "</h3></caption>\n";
                        for line in data.split("\n".to_string()) {
                            html = html + "<tr><td>" + HTTPScheme::encode(line.clone()) + "</td></tr>\n";
                        }
                    html = html + "</table>\n";
                }else{
                    html = html + "<table class='table table-bordered'>\n";
                        html = html + "  <caption><h3>Schemes</h3></caption>\n";
                        for module in session.modules.iter() {
                            let scheme = module.scheme();
                            if scheme.len() > 0 {
                                html = html + "<tr><td><a href='/" + scheme.clone() + ":///'>" + scheme.clone() + "</a></td></tr>";
                            }
                        }
                    html = html + "</table>\n";
                }
            }
        html = html + "</div>\n";

        callback(html);
    }
}
<commit_msg>Callbacks for access to session urls<commit_after>use core::clone::Clone;

use alloc::boxed::*;

use common::memory::*;
use common::string::*;
use common::url::*;

use programs::session::*;

pub struct HTTPScheme;

impl HTTPScheme {
    pub fn encode(text: String) -> String{
        let mut html = String::new();

        for c in text.chars() {
            match c {
                '&' => html = html + "&",
                '"' => html = html + """,
                '<' => html = html + "<",
                '>' => html = html + ">",
                _ => html = html + c
            }
        }

        return html;
    }
}

impl SessionModule for HTTPScheme {
    fn scheme(&self) -> String {
        return "http".to_string();
    }

    fn on_url(&mut self, session: &Session, url: &URL, callback: Box<FnBox(String)>){
        let mut path = String::new();

        for part in url.path.iter() {
            path = path + "/" + part.clone();
        }

        let html_path = path.clone();
        let html_callback: Box<FnBox(String)> = box move |content|{
            let mut html = "HTTP/1.1 200 OK\r\n".to_string()
                        + "Content-Type: text/html\r\n"
                        + "Connection: keep-alive\r\n"
                        + "\r\n";

            if html_path == "/readme".to_string() {
                html = html + "<title>Readme - Redox</title>\n";
            }else{
                html = html + "<title>Home - Redox</title>\n";
            }
            html = html + "<link rel='icon' href='data:;base64,iVBORw0KGgo='>\n";
            html = html + "<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css'>\n";
            html = html + "<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css'>\n";
            html = html + "<script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js'></script>\n";

            html = html + "<div class='container'>\n";
                html = html + "<nav class='navbar navbar-default'>\n";
                html = html + "  <div class='container-fluid'>\n";
                html = html + "    <div class='navbar-header'>\n";
                html = html + "      <button type='button' class='navbar-toggle collapsed' data-toggle='collapse' data-target='#navbar-collapse'></button>\n";
                html = html + "      <a class='navbar-brand' href='/'>Redox Web Interface</a>\n";
                html = html + "    </div>\n";
                html = html + "    <div class='collapse navbar-collapse' id='navbar-collapse'>\n";
                html = html + "      <ul class='nav navbar-nav navbar-right'>\n";

                if html_path == "/readme".to_string() {
                    html = html + "        <li><a href='/'>Home</a></li>\n";
                    html = html + "        <li class='active'><a href='/readme'>Readme</a></li>\n";
                }else{
                    html = html + "        <li class='active'><a href='/'>Home</a></li>\n";
                    html = html + "        <li><a href='/readme'>Readme</a></li>\n";
                }

                html = html + "      </ul>\n";
                html = html + "    </div>\n";
                html = html + "  </div>\n";
                html = html + "</nav>\n";

                html = html + content;
            html = html + "</div>\n";
            callback(html);
        };

        if path == "/readme".to_string() {
            session.on_url_wrapped(&URL::from_string("file:///README.md".to_string()), box move |response: String|{
                let mut html = "<div class='panel panel-default'>\n".to_string();
                    if response.data as usize > 0 {
                        let readme;
                        unsafe{
                            readme = String::from_c_str(response.data as *const u8);
                        }

                        html = html + "<div class='panel-heading'>\n";
                            html = html + "<h3 class='panel-title'><span class='glyphicon glyphicon-book'></span> README</h3>";
                        html = html + "</div>\n";

                        html = html + "<div class='panel-body'>\n";
                            let mut in_code = false;
                            for line in readme.split("\n".to_string()){
                                if line.starts_with("# ".to_string()){
                                    html = html + "<h1>" + HTTPScheme::encode(line.substr(2, line.len() - 2)) + "</h1>\n";
                                }else if line.starts_with("## ".to_string()){
                                    html = html + "<h2>" + HTTPScheme::encode(line.substr(3, line.len() - 3)) + "</h2>\n";
                                }else if line.starts_with("### ".to_string()){
                                    html = html + "<h3>" + HTTPScheme::encode(line.substr(4, line.len() - 4)) + "</h3>\n";
                                }else if line.starts_with("- ".to_string()){
                                    html = html + "<li>" + HTTPScheme::encode(line.substr(2, line.len() - 2)) + "</li>\n";
                                }else if line.starts_with("```".to_string()){
                                    if in_code {
                                        html = html + "
\n";
                                        in_code = false;
                                    }else{
                                        html = html + "
\n";
                                        in_code = true;
                                    }
                                }else{
                                    html = html + HTTPScheme::encode(line);
                                    if in_code {
                                        html = html + "\n";
                                    }else{
                                        html = html + "
\n";
                                    }
                                }
                            }
                            if in_code {
                                html = html + "
\n";
                            }
                        html = html + "
\n";
                    }else{
                        html = html + "
\n";
                            html = html + "
 Failed to open README
\n";
                        html = html + "
\n";
                    }
                html = html + "
\n";

                html_callback(html);
            });
        }else{
            let url_string = path.substr(1, path.len());
            if url_string.len() > 0 {
                let url_string_copy = url_string.clone();
                session.on_url_wrapped(&URL::from_string(url_string), box move |response: String|{
                    let mut html = "
\n".to_string();
                        html = html + "

" + HTTPScheme::encode(url_string_copy) + "

\n";
                        for line in response.split("\n".to_string()) {
                            html = html + "
" + HTTPScheme::encode(line.clone()) + "
\n";
                        }
                    html = html + "
\n";
                    html_callback(html);
                });
            }else{
                let mut html = "
\n".to_string();
                    html = html + "

Schemes

\n";
                    for module in session.modules.iter() {
                        let scheme = module.scheme();
                        if scheme.len() > 0 {
                            html = html + "
" + scheme.clone() + "
";
                        }
                    }
                html = html + "
\n";
                html_callback(html);
            }
        }
    }
}
<|endoftext|>


<commit_before>//! A library to read binary protobuf files
//!
//! This reader is developed similarly to a pull reader

#![deny(missing_docs)]
#![allow(dead_code)]

extern crate byteorder;
extern crate failure;
#[macro_use]
extern crate failure_derive;

pub mod errors;
pub mod message;
pub mod reader;
pub mod sizeofs;
pub mod writer;

pub use errors::{Error, Result};
pub use message::{MessageRead, MessageWrite};
pub use reader::{deserialize_from_slice, BytesReader, Reader};
pub use writer::{serialize_into_vec, Writer};
<commit_msg>Removed #[macro_use] to clear warning.<commit_after>//! A library to read binary protobuf files
//!
//! This reader is developed similarly to a pull reader

#![deny(missing_docs)]
#![allow(dead_code)]

extern crate byteorder;
extern crate failure;
extern crate failure_derive;

pub mod errors;
pub mod message;
pub mod reader;
pub mod sizeofs;
pub mod writer;

pub use errors::{Error, Result};
pub use message::{MessageRead, MessageWrite};
pub use reader::{deserialize_from_slice, BytesReader, Reader};
pub use writer::{serialize_into_vec, Writer};
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate chrono;

mod serializable;
mod cliente;

use std::fs::File;
use std::cmp::min;

use serializable::Serializable;
use serializable::SerializeError;

use cliente::Cliente;

use chrono::prelude::*;

struct Node<T> where T: PartialOrd + Clone {
    val: T,
    left: Option<Box<Node<T>>>,
    right: Option<Box<Node<T>>>,
}

impl<T> Node<T> where T: PartialOrd + Clone {
    fn new_leaf(val: T) -> Node<T> {
        Node {
            val,
            left: None,
            right: None,
        }
    }

    fn choose_winner(left: Node<T>, right: Node<T>) -> Node<T> {
        if left.val < right.val {
            Node {
                val: left.val.clone(),
                left: Some(Box::new(left)),
                right: Some(Box::new(right)),
            }
        } else {
            Node {
                val: right.val.clone(),
                left: Some(Box::new(left)),
                right: Some(Box::new(right)),
            }
        }
    }

    fn construct(values: Vec<T>) -> Node<T> {
        let mut iteration: Vec<Node<T>> = values.into_iter().map(|x| Node::new_leaf(x)).collect();
        let mut next_iteration = Vec::with_capacity(iteration.len() / 2);

        while iteration.len() > 1 {
            while !iteration.is_empty() {
                let right = iteration.pop().unwrap();
                let maybe_left = iteration.pop();

                let parent = match maybe_left {
                    Some(left) => Node::choose_winner(left, right),
                    None => right,
                };

                next_iteration.push(parent);
            }

            iteration = next_iteration;
            next_iteration = Vec::with_capacity(iteration.len() / 2);
        }

        iteration.pop().unwrap()
    }
}

fn nway_merge<T>(mut files: Vec<File>) -> Result<(), SerializeError> where T: PartialOrd + Clone + Serializable {
    // no more than 4 files opened at a time.

    let cutoff = min(3, files.len());
    let mut split = files.split_off(cutoff); // split 4 files

    let mut vals = Vec::with_capacity(files.len());

    for mut file in files {
        vals.push(T::deserialize(&mut file)?);
    }

    let winner = Node::construct(vals);

    Ok(())
}

fn main() {
    nway_merge::<Cliente>(vec![File::open("bucket-0").unwrap(), File::open("bucket-1").unwrap()]);

    println!("aeiou");
}

<commit_msg>This doesn't really work right now<commit_after>extern crate byteorder;
extern crate chrono;

mod serializable;
mod cliente;

use std::fs::File;
use std::cmp::{min, Ordering};

use serializable::Serializable;
use serializable::SerializeError;

use cliente::Cliente;

use chrono::prelude::*;

struct Node<T> where T: PartialOrd + Clone {
    val: T,
    left: Option<Box<Node<T>>>,
    right: Option<Box<Node<T>>>,
}

impl<T> Node<T> where T: PartialOrd + Clone {
    fn new_leaf(val: T) -> Node<T> {
        Node {
            val,
            left: None,
            right: None,
        }
    }

    fn choose_winner(left: Node<T>, right: Node<T>) -> Node<T> {
        if left.val < right.val {
            Node {
                val: left.val.clone(),
                left: Some(Box::new(left)),
                right: Some(Box::new(right)),
            }
        } else {
            Node {
                val: right.val.clone(),
                left: Some(Box::new(left)),
                right: Some(Box::new(right)),
            }
        }
    }

    fn construct(values: Vec<T>) -> Node<T> {
        let mut iteration: Vec<Node<T>> = values.into_iter().map(|x| Node::new_leaf(x)).collect();
        let mut next_iteration = Vec::with_capacity(iteration.len() / 2);

        while iteration.len() > 1 {
            while !iteration.is_empty() {
                let right = iteration.pop().unwrap();
                let maybe_left = iteration.pop();

                let parent = match maybe_left {
                    Some(left) => Node::choose_winner(left, right),
                    None => right,
                };

                next_iteration.push(parent);
            }

            iteration = next_iteration;
            next_iteration = Vec::with_capacity(iteration.len() / 2);
        }

        iteration.pop().unwrap()
    }
}

#[derive(Clone)]
struct TWrapper<T> where T: PartialOrd {
    val: Option<T>,
    file_idx: usize,
}

impl<T> PartialEq for TWrapper<T>
    where T: PartialOrd
{
    fn eq(&self, other: &TWrapper<T>) -> bool{
        self.val == other.val
    }
}

impl<T> PartialOrd for TWrapper<T>
where T: PartialOrd
{
    fn partial_cmp(&self, other: &TWrapper<T>) -> Option<Ordering> {
        self.val.partial_cmp(&other.val)
    }
}

fn replace_root<T>(root: &mut Node<TWrapper<T>>, new_val: Option<T>)
    where T: PartialOrd + Clone
{
    let mut path = Vec::new();
    let node = root;
    path.push(node);
    let is_leaf = false;

    while !is_leaf {
        if let Some(ref mut branch) = node.left {
            if branch.val.file_idx == node.val.file_idx {
                node = branch;
            }
        }
    }
}

fn nway_merge<T>(mut files: Vec<File>) -> Result<(), SerializeError> where T: PartialOrd + Clone + Serializable {
    // no more than 4 files opened at a time.

    let mut iteration = 0;
    let mut output = File::create(format!("merge-{}", iteration))?;

    let cutoff = min(3, files.len());
    let mut split = files.split_off(cutoff); // split 4 files

    let mut vals = Vec::with_capacity(files.len());

    for (idx, mut file) in files.iter_mut().enumerate() {
        let val = T::deserialize(&mut file)?;
        vals.push(TWrapper { val: Some(val) , file_idx: idx });
    }

    let mut winner = Node::construct(vals);

    // TODO: get rid of this clone
    winner.val.val.clone().unwrap().serialize(&mut output)?;

    let insert = match T::deserialize(&mut files[winner.val.file_idx]) {
        Ok(val) => Some(val),
        _ => None,
    };

    replace_root(&mut winner, insert);

    Ok(())
}

fn main() {
    /*
    let a = Cliente { codigo: 1000, nome: "aaa".to_string(), data_nascimento: Utc::now() };

    let mut f = File::create("bucket-0").unwrap();

    a.serialize(&mut f);

    let a = Cliente { codigo: 1001, nome: "aaa".to_string(), data_nascimento: Utc::now() };

//    a.serialize(&mut f);

    let mut f = File::create("bucket-1").unwrap();

    let a = Cliente { codigo: 1002, nome: "aaa".to_string(), data_nascimento: Utc::now() };

    a.serialize(&mut f);
    */

    nway_merge::<Cliente>(vec![File::open("bucket-0").unwrap(), File::open("bucket-1").unwrap()]);

    println!("aeiou");
}

<|endoftext|>


<commit_before>//! Define trait for general matrix

use std::cmp::min;
use std::fmt::Debug;
use ndarray::prelude::*;
use ndarray::LinalgScalar;
use lapack::c::Layout;

use error::{LinalgError, StrideError};
use qr::ImplQR;
use svd::ImplSVD;
use norm::ImplNorm;
use solve::ImplSolve;

/// Methods for general matrices
pub trait Matrix: Sized {
    type Scalar;
    type Vector;
    type Permutator;
    /// number of (rows, columns)
    fn size(&self) -> (usize, usize);
    /// Layout (C/Fortran) of matrix
    fn layout(&self) -> Result<Layout, StrideError>;
    /// Operator norm for L-1 norm
    fn norm_1(&self) -> Self::Scalar;
    /// Operator norm for L-inf norm
    fn norm_i(&self) -> Self::Scalar;
    /// Frobenius norm
    fn norm_f(&self) -> Self::Scalar;
    /// singular-value decomposition (SVD)
    fn svd(self) -> Result<(Self, Self::Vector, Self), LinalgError>;
    /// QR decomposition
    fn qr(self) -> Result<(Self, Self), LinalgError>;
    /// LU decomposition
    fn lu(self) -> Result<(Self::Permutator, Self, Self), LinalgError>;
    /// permutate matrix (inplace)
    fn permutate(&mut self, p: &Self::Permutator);
    /// permutate matrix (outplace)
    fn permutated(mut self, p: &Self::Permutator) -> Self {
        self.permutate(p);
        self
    }
}

impl<A> Matrix for Array<A, Ix2>
    where A: ImplQR + ImplSVD + ImplNorm + ImplSolve + LinalgScalar + Debug
{
    type Scalar = A;
    type Vector = Array<A, Ix1>;
    type Permutator = Vec<i32>;

    fn size(&self) -> (usize, usize) {
        (self.rows(), self.cols())
    }
    fn layout(&self) -> Result<Layout, StrideError> {
        let strides = self.strides();
        if min(strides[0], strides[1]) != 1 {
            return Err(StrideError {
                s0: strides[0],
                s1: strides[1],
            });;
        }
        if strides[0] < strides[1] {
            Ok(Layout::ColumnMajor)
        } else {
            Ok(Layout::RowMajor)
        }
    }
    fn norm_1(&self) -> Self::Scalar {
        let (m, n) = self.size();
        let strides = self.strides();
        if strides[0] > strides[1] {
            ImplNorm::norm_i(n, m, self.clone().into_raw_vec())
        } else {
            ImplNorm::norm_1(m, n, self.clone().into_raw_vec())
        }
    }
    fn norm_i(&self) -> Self::Scalar {
        let (m, n) = self.size();
        let strides = self.strides();
        if strides[0] > strides[1] {
            ImplNorm::norm_1(n, m, self.clone().into_raw_vec())
        } else {
            ImplNorm::norm_i(m, n, self.clone().into_raw_vec())
        }
    }
    fn norm_f(&self) -> Self::Scalar {
        let (m, n) = self.size();
        ImplNorm::norm_f(m, n, self.clone().into_raw_vec())
    }
    fn svd(self) -> Result<(Self, Self::Vector, Self), LinalgError> {
        let (n, m) = self.size();
        let layout = self.layout()?;
        let (u, s, vt) = ImplSVD::svd(layout, m, n, self.clone().into_raw_vec())?;
        let sv = Array::from_vec(s);
        let ua = Array::from_vec(u).into_shape((n, n)).unwrap();
        let va = Array::from_vec(vt).into_shape((m, m)).unwrap();
        match layout {
            Layout::RowMajor => Ok((ua, sv, va)),
            Layout::ColumnMajor => Ok((ua.reversed_axes(), sv, va.reversed_axes())),
        }
    }
    fn qr(self) -> Result<(Self, Self), LinalgError> {
        let (n, m) = self.size();
        let strides = self.strides();
        let k = min(n, m);
        let layout = self.layout()?;
        let (q, r) = try!(ImplQR::qr(layout, m, n, self.clone().into_raw_vec()));
        let (qa, ra) = if strides[0] < strides[1] {
            (Array::from_vec(q).into_shape((m, n)).unwrap().reversed_axes(),
             Array::from_vec(r).into_shape((m, n)).unwrap().reversed_axes())
        } else {
            (Array::from_vec(q).into_shape((n, m)).unwrap(), Array::from_vec(r).into_shape((n, m)).unwrap())
        };
        let qm = if m > k {
            let (qsl, _) = qa.view().split_at(Axis(1), k);
            qsl.to_owned()
        } else {
            qa
        };
        let mut rm = if n > k {
            let (rsl, _) = ra.view().split_at(Axis(0), k);
            rsl.to_owned()
        } else {
            ra
        };
        for ((i, j), val) in rm.indexed_iter_mut() {
            if i > j {
                *val = A::zero();
            }
        }
        Ok((qm, rm))
    }
    fn lu(self) -> Result<(Self::Permutator, Self, Self), LinalgError> {
        let (n, m) = self.size();
        println!("n={}, m={}", n, m);
        let k = min(n, m);
        let (p, mut a) = match self.layout()? {
            Layout::ColumnMajor => {
                println!("ColumnMajor");
                let (p, l) = ImplSolve::lu(self.layout()?, n, m, self.clone().into_raw_vec())?;
                (p, Array::from_vec(l).into_shape((m, n)).unwrap().reversed_axes())
            }
            Layout::RowMajor => {
                println!("RowMajor");
                let (p, l) = ImplSolve::lu(self.layout()?, n, m, self.clone().into_raw_vec())?;
                (p, Array::from_vec(l).into_shape((n, m)).unwrap())
            }
        };
        println!("a (after LU) = \n{:?}", &a);
        let mut lm = Array::zeros((n, k));
        for ((i, j), val) in lm.indexed_iter_mut() {
            if i > j {
                *val = a[(i, j)];
            } else if i == j {
                *val = A::one();
            }
        }
        for ((i, j), val) in a.indexed_iter_mut() {
            if i > j {
                *val = A::zero();
            }
        }
        let am = if n > k {
            a.slice(s![0..k as isize, ..]).to_owned()
        } else {
            a
        };
        println!("am = \n{:?}", am);
        Ok((p, lm, am))
    }
    fn permutate(&mut self, ipiv: &Self::Permutator) {
        let (_, m) = self.size();
        for (i, j_) in ipiv.iter().enumerate().rev() {
            let j = (j_ - 1) as usize;
            if i == j {
                continue;
            }
            for k in 0..m {
                self.swap((i, k), (j, k));
            }
        }
    }
}
<commit_msg>Remove debug code in LU<commit_after>//! Define trait for general matrix

use std::cmp::min;
use std::fmt::Debug;
use ndarray::prelude::*;
use ndarray::LinalgScalar;
use lapack::c::Layout;

use error::{LinalgError, StrideError};
use qr::ImplQR;
use svd::ImplSVD;
use norm::ImplNorm;
use solve::ImplSolve;

/// Methods for general matrices
pub trait Matrix: Sized {
    type Scalar;
    type Vector;
    type Permutator;
    /// number of (rows, columns)
    fn size(&self) -> (usize, usize);
    /// Layout (C/Fortran) of matrix
    fn layout(&self) -> Result<Layout, StrideError>;
    /// Operator norm for L-1 norm
    fn norm_1(&self) -> Self::Scalar;
    /// Operator norm for L-inf norm
    fn norm_i(&self) -> Self::Scalar;
    /// Frobenius norm
    fn norm_f(&self) -> Self::Scalar;
    /// singular-value decomposition (SVD)
    fn svd(self) -> Result<(Self, Self::Vector, Self), LinalgError>;
    /// QR decomposition
    fn qr(self) -> Result<(Self, Self), LinalgError>;
    /// LU decomposition
    fn lu(self) -> Result<(Self::Permutator, Self, Self), LinalgError>;
    /// permutate matrix (inplace)
    fn permutate(&mut self, p: &Self::Permutator);
    /// permutate matrix (outplace)
    fn permutated(mut self, p: &Self::Permutator) -> Self {
        self.permutate(p);
        self
    }
}

impl<A> Matrix for Array<A, Ix2>
    where A: ImplQR + ImplSVD + ImplNorm + ImplSolve + LinalgScalar + Debug
{
    type Scalar = A;
    type Vector = Array<A, Ix1>;
    type Permutator = Vec<i32>;

    fn size(&self) -> (usize, usize) {
        (self.rows(), self.cols())
    }
    fn layout(&self) -> Result<Layout, StrideError> {
        let strides = self.strides();
        if min(strides[0], strides[1]) != 1 {
            return Err(StrideError {
                s0: strides[0],
                s1: strides[1],
            });;
        }
        if strides[0] < strides[1] {
            Ok(Layout::ColumnMajor)
        } else {
            Ok(Layout::RowMajor)
        }
    }
    fn norm_1(&self) -> Self::Scalar {
        let (m, n) = self.size();
        let strides = self.strides();
        if strides[0] > strides[1] {
            ImplNorm::norm_i(n, m, self.clone().into_raw_vec())
        } else {
            ImplNorm::norm_1(m, n, self.clone().into_raw_vec())
        }
    }
    fn norm_i(&self) -> Self::Scalar {
        let (m, n) = self.size();
        let strides = self.strides();
        if strides[0] > strides[1] {
            ImplNorm::norm_1(n, m, self.clone().into_raw_vec())
        } else {
            ImplNorm::norm_i(m, n, self.clone().into_raw_vec())
        }
    }
    fn norm_f(&self) -> Self::Scalar {
        let (m, n) = self.size();
        ImplNorm::norm_f(m, n, self.clone().into_raw_vec())
    }
    fn svd(self) -> Result<(Self, Self::Vector, Self), LinalgError> {
        let (n, m) = self.size();
        let layout = self.layout()?;
        let (u, s, vt) = ImplSVD::svd(layout, m, n, self.clone().into_raw_vec())?;
        let sv = Array::from_vec(s);
        let ua = Array::from_vec(u).into_shape((n, n)).unwrap();
        let va = Array::from_vec(vt).into_shape((m, m)).unwrap();
        match layout {
            Layout::RowMajor => Ok((ua, sv, va)),
            Layout::ColumnMajor => Ok((ua.reversed_axes(), sv, va.reversed_axes())),
        }
    }
    fn qr(self) -> Result<(Self, Self), LinalgError> {
        let (n, m) = self.size();
        let strides = self.strides();
        let k = min(n, m);
        let layout = self.layout()?;
        let (q, r) = try!(ImplQR::qr(layout, m, n, self.clone().into_raw_vec()));
        let (qa, ra) = if strides[0] < strides[1] {
            (Array::from_vec(q).into_shape((m, n)).unwrap().reversed_axes(),
             Array::from_vec(r).into_shape((m, n)).unwrap().reversed_axes())
        } else {
            (Array::from_vec(q).into_shape((n, m)).unwrap(), Array::from_vec(r).into_shape((n, m)).unwrap())
        };
        let qm = if m > k {
            let (qsl, _) = qa.view().split_at(Axis(1), k);
            qsl.to_owned()
        } else {
            qa
        };
        let mut rm = if n > k {
            let (rsl, _) = ra.view().split_at(Axis(0), k);
            rsl.to_owned()
        } else {
            ra
        };
        for ((i, j), val) in rm.indexed_iter_mut() {
            if i > j {
                *val = A::zero();
            }
        }
        Ok((qm, rm))
    }
    fn lu(self) -> Result<(Self::Permutator, Self, Self), LinalgError> {
        let (n, m) = self.size();
        let k = min(n, m);
        let (p, l) = ImplSolve::lu(self.layout()?, n, m, self.clone().into_raw_vec())?;
        let mut a = match self.layout()? {
            Layout::ColumnMajor => Array::from_vec(l).into_shape((m, n)).unwrap().reversed_axes(),
            Layout::RowMajor => Array::from_vec(l).into_shape((n, m)).unwrap(),
        };
        let mut lm = Array::zeros((n, k));
        for ((i, j), val) in lm.indexed_iter_mut() {
            if i > j {
                *val = a[(i, j)];
            } else if i == j {
                *val = A::one();
            }
        }
        for ((i, j), val) in a.indexed_iter_mut() {
            if i > j {
                *val = A::zero();
            }
        }
        let am = if n > k {
            a.slice(s![0..k as isize, ..]).to_owned()
        } else {
            a
        };
        Ok((p, lm, am))
    }
    fn permutate(&mut self, ipiv: &Self::Permutator) {
        let (_, m) = self.size();
        for (i, j_) in ipiv.iter().enumerate().rev() {
            let j = (j_ - 1) as usize;
            if i == j {
                continue;
            }
            for k in 0..m {
                self.swap((i, k), (j, k));
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use approxeq::ApproxEq;
use point::Point2D;
use num::{One, Zero};

use num_lib::{Float, NumCast};

pub fn Matrix4<T: Float>(
        m11: T, m12: T, m13: T, m14: T,
        m21: T, m22: T, m23: T, m24: T,
        m31: T, m32: T, m33: T, m34: T,
        m41: T, m42: T, m43: T, m44: T)
     -> Matrix4<T> {
    Matrix4 {
        m11: m11, m12: m12, m13: m13, m14: m14,
        m21: m21, m22: m22, m23: m23, m24: m24,
        m31: m31, m32: m32, m33: m33, m34: m34,
        m41: m41, m42: m42, m43: m43, m44: m44
    }
}

#[derive(Debug, Copy, Clone)]
pub struct Matrix4<T> {
    pub m11: T, pub m12: T, pub m13: T, pub m14: T,
    pub m21: T, pub m22: T, pub m23: T, pub m24: T,
    pub m31: T, pub m32: T, pub m33: T, pub m34: T,
    pub m41: T, pub m42: T, pub m43: T, pub m44: T,
}

impl<T: Zero +
        One +
        ApproxEq<T> +
        Float> Matrix4<T> {
    pub fn approx_eq(&self, other: &Matrix4<T>) -> bool {
        self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) &&
        self.m13.approx_eq(&other.m13) && self.m14.approx_eq(&other.m14) &&
        self.m21.approx_eq(&other.m21) && self.m22.approx_eq(&other.m22) &&
        self.m23.approx_eq(&other.m23) && self.m24.approx_eq(&other.m24) &&
        self.m31.approx_eq(&other.m31) && self.m32.approx_eq(&other.m32) &&
        self.m33.approx_eq(&other.m33) && self.m34.approx_eq(&other.m34) &&
        self.m41.approx_eq(&other.m41) && self.m42.approx_eq(&other.m42) &&
        self.m43.approx_eq(&other.m43) && self.m44.approx_eq(&other.m44)
    }

    pub fn mul(&self, m: &Matrix4<T>) -> Matrix4<T> {
        Matrix4(m.m11*self.m11 + m.m12*self.m21 + m.m13*self.m31 + m.m14*self.m41,
                m.m11*self.m12 + m.m12*self.m22 + m.m13*self.m32 + m.m14*self.m42,
                m.m11*self.m13 + m.m12*self.m23 + m.m13*self.m33 + m.m14*self.m43,
                m.m11*self.m14 + m.m12*self.m24 + m.m13*self.m34 + m.m14*self.m44,
                m.m21*self.m11 + m.m22*self.m21 + m.m23*self.m31 + m.m24*self.m41,
                m.m21*self.m12 + m.m22*self.m22 + m.m23*self.m32 + m.m24*self.m42,
                m.m21*self.m13 + m.m22*self.m23 + m.m23*self.m33 + m.m24*self.m43,
                m.m21*self.m14 + m.m22*self.m24 + m.m23*self.m34 + m.m24*self.m44,
                m.m31*self.m11 + m.m32*self.m21 + m.m33*self.m31 + m.m34*self.m41,
                m.m31*self.m12 + m.m32*self.m22 + m.m33*self.m32 + m.m34*self.m42,
                m.m31*self.m13 + m.m32*self.m23 + m.m33*self.m33 + m.m34*self.m43,
                m.m31*self.m14 + m.m32*self.m24 + m.m33*self.m34 + m.m34*self.m44,
                m.m41*self.m11 + m.m42*self.m21 + m.m43*self.m31 + m.m44*self.m41,
                m.m41*self.m12 + m.m42*self.m22 + m.m43*self.m32 + m.m44*self.m42,
                m.m41*self.m13 + m.m42*self.m23 + m.m43*self.m33 + m.m44*self.m43,
                m.m41*self.m14 + m.m42*self.m24 + m.m43*self.m34 + m.m44*self.m44)
    }

    pub fn mul_s(&self, x: T) -> Matrix4<T> {
        Matrix4(self.m11 * x, self.m12 * x, self.m13 * x, self.m14 * x,
                self.m21 * x, self.m22 * x, self.m23 * x, self.m24 * x,
                self.m31 * x, self.m32 * x, self.m33 * x, self.m34 * x,
                self.m41 * x, self.m42 * x, self.m43 * x, self.m44 * x)
    }

    pub fn scale(&self, x: T, y: T, z: T) -> Matrix4<T> {
        Matrix4(self.m11 * x,     self.m12.clone(), self.m13.clone(), self.m14.clone(),
                self.m21.clone(), self.m22 * y,     self.m23.clone(), self.m24.clone(),
                self.m31.clone(), self.m32.clone(), self.m33 * z,     self.m34.clone(),
                self.m41.clone(), self.m42.clone(), self.m43.clone(), self.m44.clone())
    }

    /// Returns the given point transformed by this matrix.
    #[inline]
    pub fn transform_point(&self, p: &Point2D<T>) -> Point2D<T> {
        Point2D(p.x * self.m11 + p.y * self.m21 + self.m41,
                p.x * self.m12 + p.y * self.m22 + self.m42)
    }

    pub fn to_array(&self) -> [T; 16] {
        [
            self.m11.clone(), self.m12.clone(), self.m13.clone(), self.m14.clone(),
            self.m21.clone(), self.m22.clone(), self.m23.clone(), self.m24.clone(),
            self.m31.clone(), self.m32.clone(), self.m33.clone(), self.m34.clone(),
            self.m41.clone(), self.m42.clone(), self.m43.clone(), self.m44.clone()
        ]
    }

    pub fn translate(&self, x: T, y: T, z: T) -> Matrix4<T> {
        let (_0, _1): (T, T) = (Zero::zero(), One::one());
        let matrix = Matrix4(_1.clone(), _0.clone(), _0.clone(), _0.clone(),
                             _0.clone(), _1.clone(), _0.clone(), _0.clone(),
                             _0.clone(), _0.clone(), _1.clone(), _0.clone(),
                             x,  y,  z,  _1.clone());

        return self.mul(&matrix);
    }

    /// Create a 3d translation matrix
    pub fn create_translation(x: T, y: T, z: T) -> Matrix4<T> {
        let (_0, _1): (T, T) = (Zero::zero(), One::one());
        Matrix4(_1.clone(), _0.clone(), _0.clone(), _0.clone(),
                _0.clone(), _1.clone(), _0.clone(), _0.clone(),
                _0.clone(), _0.clone(), _1.clone(), _0.clone(),
                         x,          y,          z, _1.clone())
    }

    /// Create a 3d scale matrix
    pub fn create_scale(x: T, y: T, z: T) -> Matrix4<T> {
        let (_0, _1): (T, T) = (Zero::zero(), One::one());
        Matrix4(         x, _0.clone(), _0.clone(), _0.clone(),
                _0.clone(),          y, _0.clone(), _0.clone(),
                _0.clone(), _0.clone(),          z, _0.clone(),
                _0.clone(), _0.clone(), _0.clone(), _1.clone())
    }

    /// Create a 3d rotation matrix from an angle / axis.
    /// The supplied axis must be normalized.
    pub fn create_rotation(x: T, y: T, z: T, theta: T) -> Matrix4<T> {
        let _0: T = Zero::zero();
        let _1: T = One::one();
        let _2: T = NumCast::from(2).unwrap();
        let _half: T = NumCast::from(0.5).unwrap();

        let xx = x * x;
        let yy = y * y;
        let zz = z * z;

        let half_theta = theta * _half;
        let sc = half_theta.sin() * half_theta.cos();
        let sq = half_theta.sin() * half_theta.sin();

        Matrix4(
            _1.clone() - _2.clone() * (yy + zz) * sq,
            _2.clone() * (x * y * sq - z * sc),
            _2.clone() * (x * z * sq + y * sc),
            _0.clone(),

            _2.clone() * (x * y * sq + z * sc),
            _1.clone() - _2.clone() * (xx + zz) * sq,
            _2.clone() * (y * z * sq - x * sc),
            _0.clone(),

            _2.clone() * (x * z * sq - y * sc),
            _2.clone() * (y * z * sq + x * sc),
            _1.clone() - _2.clone() * (xx + yy) * sq,
            _0.clone(),

            _0.clone(),
            _0.clone(),
            _0.clone(),
            _1.clone()
        )
    }

    /// Create a 2d skew matrix
    pub fn create_skew(sx: T, sy: T) -> Matrix4<T> {
        let (_0, _1): (T, T) = (Zero::zero(), One::one());
        Matrix4(_1.clone(),         sx, _0.clone(), _0.clone(),
                        sy, _1.clone(), _0.clone(), _0.clone(),
                _0.clone(), _0.clone(), _1.clone(), _0.clone(),
                _0.clone(), _0.clone(), _0.clone(), _1.clone())
    }

    /// Create a simple perspective projection matrix
    pub fn create_perspective(d: T) -> Matrix4<T> {
        let (_0, _1): (T, T) = (Zero::zero(), One::one());
        Matrix4(_1.clone(), _0.clone(), _0.clone(), _0.clone(),
                _0.clone(), _1.clone(), _0.clone(), _0.clone(),
                _0.clone(), _0.clone(), _1.clone(), -_1.clone() / d,
                _0.clone(), _0.clone(), _0.clone(), _1.clone())
    }
}

// TODO(gw): Move ortho and identity into static functions of the Matrix type.
pub fn ortho<T: Zero + One + Float>
        (left: T,
         right: T,
         bottom: T,
         top: T,
         near: T,
         far: T)
      -> Matrix4<T> {
    let _2: T = NumCast::from(2).unwrap();
    let _1: T = One::one();
    let _0: T = Zero::zero();

    let tx = -((right + left) / (right - left));
    let ty = -((top + bottom) / (top - bottom));
    let tz = -((far + near) / (far - near));

    Matrix4(_2 / (right - left), _0.clone(),          _0.clone(),         _0.clone(),
            _0.clone(),          _2 / (top - bottom), _0.clone(),         _0.clone(),
            _0.clone(),          _0.clone(),          -_2 / (far - near), _0.clone(),
            tx,                  ty,                  tz,                 _1.clone())
}

pub fn identity<T: Zero + One + Float>() -> Matrix4<T> {
    let (_0, _1): (T, T) = (Zero::zero(), One::one());
    Matrix4(_1.clone(), _0.clone(), _0.clone(), _0.clone(),
            _0.clone(), _1.clone(), _0.clone(), _0.clone(),
            _0.clone(), _0.clone(), _1.clone(), _0.clone(),
            _0.clone(), _0.clone(), _0.clone(), _1.clone())
}

#[test]
pub fn test_ortho() {
    let (left, right, bottom, top) = (0.0f32, 1.0f32, 0.1f32, 1.0f32);
    let (near, far) = (-1.0f32, 1.0f32);
    let result = ortho(left, right, bottom, top, near, far);
    let expected = Matrix4(2.0,  0.0,         0.0,  0.0,
                           0.0,  2.22222222,  0.0,  0.0,
                           0.0,  0.0,         -1.0, 0.0,
                           -1.0, -1.22222222, -0.0, 1.0);
    debug!("result={:?} expected={:?}", result, expected);
    assert!(result.approx_eq(&expected));
}

<commit_msg>Make Matrix4 a concrete type.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use approxeq::ApproxEq;
use point::Point2D;

pub fn Matrix4(
        m11: f32, m12: f32, m13: f32, m14: f32,
        m21: f32, m22: f32, m23: f32, m24: f32,
        m31: f32, m32: f32, m33: f32, m34: f32,
        m41: f32, m42: f32, m43: f32, m44: f32)
     -> Matrix4 {
    Matrix4 {
        m11: m11, m12: m12, m13: m13, m14: m14,
        m21: m21, m22: m22, m23: m23, m24: m24,
        m31: m31, m32: m32, m33: m33, m34: m34,
        m41: m41, m42: m42, m43: m43, m44: m44
    }
}

#[derive(Debug, Copy, Clone)]
pub struct Matrix4 {
    pub m11: f32, pub m12: f32, pub m13: f32, pub m14: f32,
    pub m21: f32, pub m22: f32, pub m23: f32, pub m24: f32,
    pub m31: f32, pub m32: f32, pub m33: f32, pub m34: f32,
    pub m41: f32, pub m42: f32, pub m43: f32, pub m44: f32,
}

impl Matrix4 {
    pub fn approx_eq(&self, other: &Matrix4) -> bool {
        self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) &&
        self.m13.approx_eq(&other.m13) && self.m14.approx_eq(&other.m14) &&
        self.m21.approx_eq(&other.m21) && self.m22.approx_eq(&other.m22) &&
        self.m23.approx_eq(&other.m23) && self.m24.approx_eq(&other.m24) &&
        self.m31.approx_eq(&other.m31) && self.m32.approx_eq(&other.m32) &&
        self.m33.approx_eq(&other.m33) && self.m34.approx_eq(&other.m34) &&
        self.m41.approx_eq(&other.m41) && self.m42.approx_eq(&other.m42) &&
        self.m43.approx_eq(&other.m43) && self.m44.approx_eq(&other.m44)
    }

    pub fn mul(&self, m: &Matrix4) -> Matrix4 {
        Matrix4(m.m11*self.m11 + m.m12*self.m21 + m.m13*self.m31 + m.m14*self.m41,
                m.m11*self.m12 + m.m12*self.m22 + m.m13*self.m32 + m.m14*self.m42,
                m.m11*self.m13 + m.m12*self.m23 + m.m13*self.m33 + m.m14*self.m43,
                m.m11*self.m14 + m.m12*self.m24 + m.m13*self.m34 + m.m14*self.m44,
                m.m21*self.m11 + m.m22*self.m21 + m.m23*self.m31 + m.m24*self.m41,
                m.m21*self.m12 + m.m22*self.m22 + m.m23*self.m32 + m.m24*self.m42,
                m.m21*self.m13 + m.m22*self.m23 + m.m23*self.m33 + m.m24*self.m43,
                m.m21*self.m14 + m.m22*self.m24 + m.m23*self.m34 + m.m24*self.m44,
                m.m31*self.m11 + m.m32*self.m21 + m.m33*self.m31 + m.m34*self.m41,
                m.m31*self.m12 + m.m32*self.m22 + m.m33*self.m32 + m.m34*self.m42,
                m.m31*self.m13 + m.m32*self.m23 + m.m33*self.m33 + m.m34*self.m43,
                m.m31*self.m14 + m.m32*self.m24 + m.m33*self.m34 + m.m34*self.m44,
                m.m41*self.m11 + m.m42*self.m21 + m.m43*self.m31 + m.m44*self.m41,
                m.m41*self.m12 + m.m42*self.m22 + m.m43*self.m32 + m.m44*self.m42,
                m.m41*self.m13 + m.m42*self.m23 + m.m43*self.m33 + m.m44*self.m43,
                m.m41*self.m14 + m.m42*self.m24 + m.m43*self.m34 + m.m44*self.m44)
    }

    pub fn mul_s(&self, x: f32) -> Matrix4 {
        Matrix4(self.m11 * x, self.m12 * x, self.m13 * x, self.m14 * x,
                self.m21 * x, self.m22 * x, self.m23 * x, self.m24 * x,
                self.m31 * x, self.m32 * x, self.m33 * x, self.m34 * x,
                self.m41 * x, self.m42 * x, self.m43 * x, self.m44 * x)
    }

    pub fn scale(&self, x: f32, y: f32, z: f32) -> Matrix4 {
        Matrix4(self.m11 * x, self.m12,     self.m13,     self.m14,
                self.m21    , self.m22 * y, self.m23,     self.m24,
                self.m31    , self.m32,     self.m33 * z, self.m34,
                self.m41    , self.m42,     self.m43,     self.m44)
    }

    /// Returns the given point transformed by this matrix.
    #[inline]
    pub fn transform_point(&self, p: &Point2D<f32>) -> Point2D<f32> {
        Point2D(p.x * self.m11 + p.y * self.m21 + self.m41,
                p.x * self.m12 + p.y * self.m22 + self.m42)
    }

    pub fn to_array(&self) -> [f32; 16] {
        [
            self.m11, self.m12, self.m13, self.m14,
            self.m21, self.m22, self.m23, self.m24,
            self.m31, self.m32, self.m33, self.m34,
            self.m41, self.m42, self.m43, self.m44
        ]
    }

    pub fn translate(&self, x: f32, y: f32, z: f32) -> Matrix4 {
        let matrix = Matrix4(1.0, 0.0, 0.0, 0.0,
                             0.0, 1.0, 0.0, 0.0,
                             0.0, 0.0, 1.0, 0.0,
                               x,   y,   z, 1.0);

        return self.mul(&matrix);
    }

    /// Create a 3d translation matrix
    pub fn create_translation(x: f32, y: f32, z: f32) -> Matrix4 {
        Matrix4(1.0, 0.0, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, 1.0, 0.0,
                  x,   y,   z, 1.0)
    }

    /// Create a 3d scale matrix
    pub fn create_scale(x: f32, y: f32, z: f32) -> Matrix4 {
        Matrix4(  x, 0.0, 0.0, 0.0,
                0.0,   y, 0.0, 0.0,
                0.0, 0.0,   z, 0.0,
                0.0, 0.0, 0.0, 1.0)
    }

    /// Create a 3d rotation matrix from an angle / axis.
    /// The supplied axis must be normalized.
    pub fn create_rotation(x: f32, y: f32, z: f32, theta: f32) -> Matrix4 {
        let xx = x * x;
        let yy = y * y;
        let zz = z * z;

        let half_theta = theta * 0.5;
        let sc = half_theta.sin() * half_theta.cos();
        let sq = half_theta.sin() * half_theta.sin();

        Matrix4(
            1.0 - 2.0 * (yy + zz) * sq,
            2.0 * (x * y * sq - z * sc),
            2.0 * (x * z * sq + y * sc),
            0.0,

            2.0 * (x * y * sq + z * sc),
            1.0 - 2.0 * (xx + zz) * sq,
            2.0 * (y * z * sq - x * sc),
            0.0,

            2.0 * (x * z * sq - y * sc),
            2.0 * (y * z * sq + x * sc),
            1.0 - 2.0 * (xx + yy) * sq,
            0.0,

            0.0,
            0.0,
            0.0,
            1.0
        )
    }

    /// Create a 2d skew matrix
    pub fn create_skew(sx: f32, sy: f32) -> Matrix4 {
        Matrix4(1.0,  sx, 0.0, 0.0,
                 sy, 1.0, 0.0, 0.0,
                0.0, 0.0, 1.0, 0.0,
                0.0, 0.0, 0.0, 1.0)
    }

    /// Create a simple perspective projection matrix
    pub fn create_perspective(d: f32) -> Matrix4 {
        Matrix4(1.0, 0.0, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, 1.0, -1.0 / d,
                0.0, 0.0, 0.0, 1.0)
    }
}

// TODO(gw): Move ortho and identity into static functions of the Matrix type.
pub fn ortho(left: f32, right: f32,
             bottom: f32, top: f32,
             near: f32, far: f32) -> Matrix4 {
    let tx = -((right + left) / (right - left));
    let ty = -((top + bottom) / (top - bottom));
    let tz = -((far + near) / (far - near));

    Matrix4(2.0 / (right - left),
            0.0,
            0.0,
            0.0,

            0.0,
            2.0 / (top - bottom),
            0.0,
            0.0,

            0.0,
            0.0,
            -2.0 / (far - near),
            0.0,

            tx,
            ty,
            tz,
            1.0)
}

pub fn identity() -> Matrix4 {
    Matrix4(1.0, 0.0, 0.0, 0.0,
            0.0, 1.0, 0.0, 0.0,
            0.0, 0.0, 1.0, 0.0,
            0.0, 0.0, 0.0, 1.0)
}

#[test]
pub fn test_ortho() {
    let (left, right, bottom, top) = (0.0f32, 1.0f32, 0.1f32, 1.0f32);
    let (near, far) = (-1.0f32, 1.0f32);
    let result = ortho(left, right, bottom, top, near, far);
    let expected = Matrix4(2.0,  0.0,         0.0,  0.0,
                           0.0,  2.22222222,  0.0,  0.0,
                           0.0,  0.0,         -1.0, 0.0,
                           -1.0, -1.22222222, -0.0, 1.0);
    debug!("result={:?} expected={:?}", result, expected);
    assert!(result.approx_eq(&expected));
}

<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::hash_map::{Entry, HashMap};
use std::collections::hash_set::HashSet;
use std::rc::{Rc, Weak};
use uuid::Uuid;

use alloc::{Alloc, AllocBox};
use js_types::js_type::{JsVar, JsType, JsPtrEnum};

pub struct Scope {
    pub parent: Option<Rc<Scope>>,
    alloc_box: Rc<RefCell<AllocBox>>,
    get_roots: Box<Fn() -> HashSet<Uuid>>,
}

impl Scope {
    pub fn new<F>(alloc_box: &Rc<RefCell<AllocBox>>, get_roots: F) -> Scope
        where F: Fn() -> HashSet<Uuid> + 'static {
        Scope {
            parent: None,
            alloc_box: alloc_box.clone(),
            get_roots: Box::new(get_roots),
        }
    }

    pub fn as_child<F>(parent: &Rc<Scope>, alloc_box: &Rc<RefCell<AllocBox>>, get_roots: F) -> Scope
        where F: Fn() -> HashSet<Uuid> + 'static {
        Scope {
            parent: Some(parent.clone()),
            alloc_box: alloc_box.clone(),
            get_roots: Box::new(get_roots),
        }
    }

    pub fn set_parent(&mut self, parent: &Rc<Scope>) {
        self.parent = Some(parent.clone());
    }

    pub fn alloc(&mut self, uuid: Uuid, ptr: JsPtrEnum) -> Uuid {
        self.alloc_box.borrow_mut().alloc(uuid, ptr)
    }

    pub fn dealloc(&mut self, uuid: &Uuid) -> bool {
        self.alloc_box.borrow_mut().dealloc(uuid)
    }

    pub fn get_ptr_copy(&self, uuid: &Uuid) -> Option<JsPtrEnum> {
        self.alloc_box.borrow().find_id(uuid).map(|var| var.borrow().clone())
    }

    pub fn update_ptr(&mut self, uuid: &Uuid, ptr: JsPtrEnum) -> bool {
        self.alloc_box.borrow_mut().update_var(uuid, ptr)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::cell::RefCell;
    use std::collections::hash_set::HashSet;
    use std::rc::{Rc, Weak};
    use uuid::Uuid;

    use alloc::{Alloc, AllocBox};
    use js_types::js_type::{JsVar, JsType, JsPtrEnum, JsKey, JsKeyEnum};
    use js_types::js_obj::JsObjStruct;
    use js_types::js_str::JsStrStruct;

    fn dummy_get_roots() -> HashSet<Uuid> {
        HashSet::new()
    }

    fn make_alloc_box() -> Rc<RefCell<AllocBox>> {
        Rc::new(RefCell::new(AllocBox::new()))
    }

    fn make_num(i: f64) -> JsVar {
        JsVar::new(JsType::JsNum(i))
    }

    fn make_obj(alloc_box: Rc<RefCell<AllocBox>>, kvs: Vec<(JsKey, JsVar)>) -> JsVar {
        let var = JsVar::new(JsType::JsPtr);
        alloc_box.borrow_mut()
            .alloc(var.uuid, JsPtrEnum::JsObj(JsObjStruct::new(None, "test", kvs)));
        var
    }

    #[test]
    fn test_new_scope() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        assert!(test_scope.parent.is_none());
    }

    #[test]
    fn test_as_child_scope() {
        let alloc_box = make_alloc_box();
        let parent_scope = Rc::new(Scope::new(&alloc_box, dummy_get_roots));
        let mut test_scope = Scope::as_child(&parent_scope, &alloc_box, dummy_get_roots);
        assert!(test_scope.parent.is_some());
    }

    #[test]
    fn test_set_parent() {
        let alloc_box = make_alloc_box();
        let parent_scope = Rc::new(Scope::new(&alloc_box, dummy_get_roots));
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        assert!(test_scope.parent.is_none());
        test_scope.set_parent(&parent_scope);
        assert!(test_scope.parent.is_some());
    }

    #[test]
    fn test_alloc() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsNull);
        assert_eq!(test_id, test_var.uuid);
    }

    #[test]
    fn test_dealloc() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsNull);
        let bad_uuid = Uuid::new_v4();
        assert!(test_scope.dealloc(&test_id));
        assert!(!test_scope.dealloc(&bad_uuid));
    }

    #[test]
    fn test_get_ptr_copy() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsNull);
        let bad_uuid = Uuid::new_v4();

        let ptr_copy = test_scope.get_ptr_copy(&test_id);
        assert!(ptr_copy.is_some());

        // FIXME it's kind of problematic that UUIDs are separated
        // from ptr types
        //let ptr = ptr_copy.unwrap();
        //assert_eq!(ptr.uuid, test_id);

        let bad_copy = test_scope.get_ptr_copy(&bad_uuid);
        assert!(bad_copy.is_none());
    }

    #[test]
    fn test_update_ptr() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsNull);
        let mut update = test_scope.get_ptr_copy(&test_id).unwrap();
        update = JsPtrEnum::JsStr(JsStrStruct::new("test"));
        assert!(test_scope.update_ptr(&test_id, update));

        let update = test_scope.get_ptr_copy(&test_id).unwrap();
        match update {
            JsPtrEnum::JsStr(JsStrStruct{text: ref s}) => assert_eq!(s, "test"),
            _ => ()
        }
        test_scope.dealloc(&test_id);
        assert!(!test_scope.update_ptr(&test_id, update));
    }
}
<commit_msg>Make get_roots public on Scope<commit_after>use std::cell::RefCell;
use std::collections::hash_map::{Entry, HashMap};
use std::collections::hash_set::HashSet;
use std::rc::{Rc, Weak};
use uuid::Uuid;

use alloc::{Alloc, AllocBox};
use js_types::js_type::{JsVar, JsType, JsPtrEnum};

pub struct Scope {
    pub parent: Option<Rc<Scope>>,
    alloc_box: Rc<RefCell<AllocBox>>,
    pub get_roots: Box<Fn() -> HashSet<Uuid>>,
}

impl Scope {
    pub fn new<F>(alloc_box: &Rc<RefCell<AllocBox>>, get_roots: F) -> Scope
        where F: Fn() -> HashSet<Uuid> + 'static {
        Scope {
            parent: None,
            alloc_box: alloc_box.clone(),
            get_roots: Box::new(get_roots),
        }
    }

    pub fn as_child<F>(parent: &Rc<Scope>, alloc_box: &Rc<RefCell<AllocBox>>, get_roots: F) -> Scope
        where F: Fn() -> HashSet<Uuid> + 'static {
        Scope {
            parent: Some(parent.clone()),
            alloc_box: alloc_box.clone(),
            get_roots: Box::new(get_roots),
        }
    }

    pub fn set_parent(&mut self, parent: &Rc<Scope>) {
        self.parent = Some(parent.clone());
    }

    pub fn alloc(&mut self, uuid: Uuid, ptr: JsPtrEnum) -> Uuid {
        self.alloc_box.borrow_mut().alloc(uuid, ptr)
    }

    pub fn dealloc(&mut self, uuid: &Uuid) -> bool {
        self.alloc_box.borrow_mut().dealloc(uuid)
    }

    pub fn get_ptr_copy(&self, uuid: &Uuid) -> Option<JsPtrEnum> {
        self.alloc_box.borrow().find_id(uuid).map(|var| var.borrow().clone())
    }

    pub fn update_ptr(&mut self, uuid: &Uuid, ptr: JsPtrEnum) -> bool {
        self.alloc_box.borrow_mut().update_var(uuid, ptr)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::cell::RefCell;
    use std::collections::hash_set::HashSet;
    use std::rc::{Rc, Weak};
    use uuid::Uuid;

    use alloc::{Alloc, AllocBox};
    use js_types::js_type::{JsVar, JsType, JsPtrEnum, JsKey, JsKeyEnum};
    use js_types::js_obj::JsObjStruct;
    use js_types::js_str::JsStrStruct;

    fn dummy_get_roots() -> HashSet<Uuid> {
        HashSet::new()
    }

    fn make_alloc_box() -> Rc<RefCell<AllocBox>> {
        Rc::new(RefCell::new(AllocBox::new()))
    }

    fn make_num(i: f64) -> JsVar {
        JsVar::new(JsType::JsNum(i))
    }

    fn make_obj(alloc_box: Rc<RefCell<AllocBox>>, kvs: Vec<(JsKey, JsVar)>) -> JsVar {
        let var = JsVar::new(JsType::JsPtr);
        alloc_box.borrow_mut()
            .alloc(var.uuid, JsPtrEnum::JsObj(JsObjStruct::new(None, "test", kvs)));
        var
    }

    #[test]
    fn test_new_scope() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        assert!(test_scope.parent.is_none());
    }

    #[test]
    fn test_as_child_scope() {
        let alloc_box = make_alloc_box();
        let parent_scope = Rc::new(Scope::new(&alloc_box, dummy_get_roots));
        let mut test_scope = Scope::as_child(&parent_scope, &alloc_box, dummy_get_roots);
        assert!(test_scope.parent.is_some());
    }

    #[test]
    fn test_set_parent() {
        let alloc_box = make_alloc_box();
        let parent_scope = Rc::new(Scope::new(&alloc_box, dummy_get_roots));
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        assert!(test_scope.parent.is_none());
        test_scope.set_parent(&parent_scope);
        assert!(test_scope.parent.is_some());
    }

    #[test]
    fn test_alloc() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsNull);
        assert_eq!(test_id, test_var.uuid);
    }

    #[test]
    fn test_dealloc() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsNull);
        let bad_uuid = Uuid::new_v4();
        assert!(test_scope.dealloc(&test_id));
        assert!(!test_scope.dealloc(&bad_uuid));
    }

    #[test]
    fn test_get_ptr_copy() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsNull);
        let bad_uuid = Uuid::new_v4();

        let ptr_copy = test_scope.get_ptr_copy(&test_id);
        assert!(ptr_copy.is_some());

        // FIXME it's kind of problematic that UUIDs are separated
        // from ptr types
        //let ptr = ptr_copy.unwrap();
        //assert_eq!(ptr.uuid, test_id);

        let bad_copy = test_scope.get_ptr_copy(&bad_uuid);
        assert!(bad_copy.is_none());
    }

    #[test]
    fn test_update_ptr() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsNull);
        let mut update = test_scope.get_ptr_copy(&test_id).unwrap();
        update = JsPtrEnum::JsStr(JsStrStruct::new("test"));
        assert!(test_scope.update_ptr(&test_id, update));

        let update = test_scope.get_ptr_copy(&test_id).unwrap();
        match update {
            JsPtrEnum::JsStr(JsStrStruct{text: ref s}) => assert_eq!(s, "test"),
            _ => ()
        }
        test_scope.dealloc(&test_id);
        assert!(!test_scope.update_ptr(&test_id, update));
    }
}
<|endoftext|>


<commit_before>use std::ops::{Mul,Add};
use num::traits::{Zero,One,Float};

#[derive(PartialEq,Debug)]
pub struct Vec3<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Zero + Copy + Clone {
    x: T,
    y: T,
    z: T,
}

impl <T> Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Zero + Copy + Clone {
    pub fn new(xx: T, yy: T, zz: T) -> Vec3<T> {
        Vec3 { x: xx, y: yy, z: zz }
    }

    pub fn zero() -> Vec3<T> {
        Vec3::new(T::zero(), T::zero(), T::zero())
    }

    pub fn diagonal(xx: T) -> Vec3<T> {
        Vec3::new(xx, xx, xx)
    }
}

impl <'a, T > Mul<Vec3<T>> for &'a Vec3<T> where T: Mul<T, Output = T> + Zero + Copy + Clone {
    type Output = T;

    fn mul(self, rhs: Vec3<T>) -> T {
        return self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }
}

impl <T> Vec3<T> where T: Mul<T, Output=T> + One + Zero + Float + Clone + Copy {
    pub fn length(& self) -> T {
        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
    }

    pub fn normalize(&mut self) {
        let length: T = self.length();
        if length > T::zero() {
            let inverse_length = T::one() / length;

            self.x = self.x * inverse_length;
            self.y = self.y * inverse_length;
            self.z = self.z * inverse_length;
        }
    }
}

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

    #[test]
    fn should_be_created_with_constructor() {
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        assert_eq!(v, Vec3 { x: 0.0, y: 1.0, z: 2.0 });
    }

    #[test]
    fn should_initialize_to_zero_vector() {
        let v: Vec3<f64> = Vec3::zero();

        assert_eq!(v, Vec3::<f64>{ x: 0.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_initialize_to_diagonal_vector() {
        let v: Vec3<f64> = Vec3::diagonal(1.0);

        assert_eq!(v, Vec3::<f64>{ x: 1.0, y: 1.0, z: 1.0 });
    }

    #[test]
    fn should_know_dot_product() {
        let u: Vec3<f64> = Vec3::diagonal(1.0);
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        let dot_product: f64 = &u * v;

        assert_eq!(dot_product, 3.0);
    }

    #[test]
    fn should_know_its_length() {
        let v: Vec3<f64> = Vec3 { x: 0.0, y: 0.0, z: 0.0 };

        assert_eq!(v.length(), 0.0);
    }

    #[test]
    fn should_be_able_to_normalize() {
        let mut v: Vec3<f64> = Vec3::new(3.0, 0.0, 0.0);
        v.normalize();

        assert_eq!(v, Vec3 { x: 1.0, y: 0.0, z: 0.0 });
    }
}
<commit_msg>Do not implement trait Mul, us dot<commit_after>use std::ops::{Mul,Add};
use num::traits::{Zero,One,Float};

#[derive(PartialEq,Debug)]
pub struct Vec3<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Zero + Copy + Clone {
    x: T,
    y: T,
    z: T,
}

impl <T> Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Zero + Copy + Clone {
    pub fn new(xx: T, yy: T, zz: T) -> Vec3<T> {
        Vec3 { x: xx, y: yy, z: zz }
    }

    pub fn zero() -> Vec3<T> {
        Vec3::new(T::zero(), T::zero(), T::zero())
    }

    pub fn diagonal(xx: T) -> Vec3<T> {
        Vec3::new(xx, xx, xx)
    }

    pub fn dot(self, rhs: Vec3<T>) -> T {
         return self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }
}

impl <T> Vec3<T> where T: Mul<T, Output=T> + One + Zero + Float + Clone + Copy {
    pub fn length(& self) -> T {
        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
    }

    pub fn normalize(&mut self) {
        let length: T = self.length();
        if length > T::zero() {
            let inverse_length = T::one() / length;

            self.x = self.x * inverse_length;
            self.y = self.y * inverse_length;
            self.z = self.z * inverse_length;
        }
    }
}

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

    #[test]
    fn should_be_created_with_constructor() {
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        assert_eq!(v, Vec3 { x: 0.0, y: 1.0, z: 2.0 });
    }

    #[test]
    fn should_initialize_to_zero_vector() {
        let v: Vec3<f64> = Vec3::zero();

        assert_eq!(v, Vec3::<f64>{ x: 0.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_initialize_to_diagonal_vector() {
        let v: Vec3<f64> = Vec3::diagonal(1.0);

        assert_eq!(v, Vec3::<f64>{ x: 1.0, y: 1.0, z: 1.0 });
    }

    #[test]
    fn should_know_dot_product() {
        let u: Vec3<f64> = Vec3::diagonal(1.0);
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        let dot_product: f64 = u.dot(v);

        assert_eq!(dot_product, 3.0);
    }

    #[test]
    fn should_know_its_length() {
        let v: Vec3<f64> = Vec3 { x: 0.0, y: 0.0, z: 0.0 };

        assert_eq!(v.length(), 0.0);
    }

    #[test]
    fn should_be_able_to_normalize() {
        let mut v: Vec3<f64> = Vec3::new(3.0, 0.0, 0.0);
        v.normalize();

        assert_eq!(v, Vec3 { x: 1.0, y: 0.0, z: 0.0 });
    }
}
<|endoftext|>


<commit_before>use std::ops::{Mul,Add};
use num::traits::{Zero,Float};

#[derive(PartialEq,Debug)]
pub struct Vec3<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Zero + Copy + Clone {
    x: T,
    y: T,
    z: T,
}

impl <T> Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Zero + Copy + Clone {
    pub fn new(xx: T, yy: T, zz: T) -> Vec3<T> {
        Vec3 { x: xx, y: yy, z: zz }
    }

    pub fn zero() -> Vec3<T> {
        Vec3::new(T::zero(), T::zero(), T::zero())
    }

    pub fn diagonal(xx: T) -> Vec3<T> {
        Vec3::new(xx, xx, xx)
    }
}

impl <T> Mul<Vec3<T>> for Vec3<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Zero + Copy + Clone {
    type Output = T;

    fn mul(self, rhs: Vec3<T>) -> T {
        return self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }
}

impl <T> Vec3<T> where T: Mul<T, Output=T> + Add<T, Output=T> + Zero + Float + Clone + Copy {
    pub fn norm(self) -> T {
        (self.x * self.x + self.y * self.y + self.z * self.z)
    }
}

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

    #[test]
    fn should_be_created_with_constructor() {
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        assert_eq!(v, Vec3 { x: 0.0, y: 1.0, z: 2.0 });
    }

    #[test]
    fn should_initialize_to_zero_vector() {
        let v: Vec3<f64> = Vec3::zero();

        assert_eq!(v, Vec3::<f64>{ x: 0.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_initialize_to_diagonal_vector() {
        let v: Vec3<f64> = Vec3::diagonal(1.0);

        assert_eq!(v, Vec3::<f64>{ x: 1.0, y: 1.0, z: 1.0 });
    }

    #[test]
    fn should_know_dot_product() {
        let u: Vec3<f64> = Vec3::diagonal(1.0);
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        let dot_product: f64 = u * v;

        assert_eq!(dot_product, 3.0);
    }

    #[test]
    fn should_know_its_norm() {
        let v: Vec3<f64> = Vec3 { x: 0.0, y: 0.0, z: 0.0 };

        assert_eq!(v.norm(), 0.0);
    }
}
<commit_msg>Calculate length instead of a norm<commit_after>use std::ops::{Mul,Add};
use num::traits::{Zero,Float};

#[derive(PartialEq,Debug)]
pub struct Vec3<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Zero + Copy + Clone {
    x: T,
    y: T,
    z: T,
}

impl <T> Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Zero + Copy + Clone {
    pub fn new(xx: T, yy: T, zz: T) -> Vec3<T> {
        Vec3 { x: xx, y: yy, z: zz }
    }

    pub fn zero() -> Vec3<T> {
        Vec3::new(T::zero(), T::zero(), T::zero())
    }

    pub fn diagonal(xx: T) -> Vec3<T> {
        Vec3::new(xx, xx, xx)
    }
}

impl <T> Mul<Vec3<T>> for Vec3<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Zero + Copy + Clone {
    type Output = T;

    fn mul(self, rhs: Vec3<T>) -> T {
        return self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }
}

impl <T> Vec3<T> where T: Mul<T, Output=T> + Add<T, Output=T> + Zero + Float + Clone + Copy {
    pub fn length(self) -> T {
        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
    }
}

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

    #[test]
    fn should_be_created_with_constructor() {
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        assert_eq!(v, Vec3 { x: 0.0, y: 1.0, z: 2.0 });
    }

    #[test]
    fn should_initialize_to_zero_vector() {
        let v: Vec3<f64> = Vec3::zero();

        assert_eq!(v, Vec3::<f64>{ x: 0.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_initialize_to_diagonal_vector() {
        let v: Vec3<f64> = Vec3::diagonal(1.0);

        assert_eq!(v, Vec3::<f64>{ x: 1.0, y: 1.0, z: 1.0 });
    }

    #[test]
    fn should_know_dot_product() {
        let u: Vec3<f64> = Vec3::diagonal(1.0);
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        let dot_product: f64 = u * v;

        assert_eq!(dot_product, 3.0);
    }

    #[test]
    fn should_know_its_length() {
        let v: Vec3<f64> = Vec3 { x: 0.0, y: 0.0, z: 0.0 };

        assert_eq!(v.length(), 0.0);
    }
}
<|endoftext|>


<commit_before>use std::num;
use std::vec;
use addressable::Addressable;

pub struct Ram<ADDR> {
	data: ~[u8],
}

impl<ADDR: Int> Addressable<ADDR, u8> for Ram<ADDR> {
	pub fn get (&self, addr: ADDR) -> u8 {
		let i: uint = num::cast(addr);
		if i >= self.data.len() { fail!("ram: read beyond memory bounds ($%x >= $%x)", i, self.data.len()); }
		self.data[i]
	}

	pub fn set (&mut self, addr: ADDR, data: u8) {
		let i: uint = num::cast(addr);
		if i >= self.data.len() { fail!("ram: write beyond memory bounds ($%x >= $%x)", i, self.data.len()); }
		self.data[i] = data;
	}
}

impl<ADDR: Int> Ram<ADDR> {
	pub fn new (size: uint) -> ~Ram<ADDR> {
		~Ram { data: vec::from_elem(size, 0) }
	}
}

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

	#[test]
	fn test () {
		let mut memory = Ram::new(1024);
		memory.set(0x0123, 0x55);
		assert_eq!(memory.get(0x0123), 0x55);
	}
}
<commit_msg>Made internal storage vector private<commit_after>use std::num;
use std::vec;
use addressable::Addressable;

pub struct Ram<ADDR> {
	priv data: ~[u8],
}

impl<ADDR: Int> Addressable<ADDR, u8> for Ram<ADDR> {
	pub fn get (&self, addr: ADDR) -> u8 {
		let i: uint = num::cast(addr);
		if i >= self.data.len() { fail!("ram: read beyond memory bounds ($%x >= $%x)", i, self.data.len()); }
		self.data[i]
	}

	pub fn set (&mut self, addr: ADDR, data: u8) {
		let i: uint = num::cast(addr);
		if i >= self.data.len() { fail!("ram: write beyond memory bounds ($%x >= $%x)", i, self.data.len()); }
		self.data[i] = data;
	}
}

impl<ADDR: Int> Ram<ADDR> {
	pub fn new (size: uint) -> ~Ram<ADDR> {
		~Ram { data: vec::from_elem(size, 0) }
	}
}

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

	#[test]
	fn test () {
		let mut memory = Ram::new(1024);
		memory.set(0x0123, 0x55);
		assert_eq!(memory.get(0x0123), 0x55);
	}
}
<|endoftext|>