<commit_before>use config::{parse_config, Benchmark, Config};
use Commit;
use git2;
use Push;
use repo::Workspace;

use std::collections::HashMap;
use std::io;
use std::path::Path;
use std::process::{Command, ExitStatus, Output};
use std::str;

/// `(val, percentage_change)`
#[derive(Debug, Clone)]
pub enum BenchmarkResult<T> {
    Improvement(T, f64),
    Regression(T, f64),
    Neutral(T, f64),
}

#[derive(Debug, Clone)]
pub struct TastingResult {
    pub branch: Option<String>,
    pub commit: Commit,
    pub build: bool,
    pub test: bool,
    pub bench: bool,
    pub results: Option<Vec<(Benchmark, ExitStatus, HashMap<String, BenchmarkResult<f64>>)>>,
}

fn run_benchmark(workdir: &str, cfg: &Config, bench: &Benchmark, timeout: Option<u64>) -> Output {
    let mut cmd = if cfg.version.is_none() || cfg.version.unwrap() < 2 {
        // older taster configs assume an implied "cargo" prefix on each benchmark command
        match timeout {
            None => {
                let mut cmd = Command::new("cargo");
                cmd.arg(&bench.cmd);
                cmd
            }
            Some(timeout) => {
                let mut cmd = Command::new("timeout");
                cmd.arg("-k")
                    .arg(&format!("{}s", timeout + 30))
                    .arg(&format!("{}s", timeout))
                    .arg("cargo")
                    .arg(&bench.cmd);
                cmd
            }
        }
    } else {
        // from taster config version 2, we no longer assume an implicit "cargo" prefix on
        // benchmark commands
        match timeout {
            None => Command::new(&bench.cmd),
            Some(timeout) => {
                let mut cmd = Command::new("timeout");
                cmd.arg("-k")
                    .arg(&format!("{}s", timeout + 30))
                    .arg(&format!("{}s", timeout))
                    .arg(&bench.cmd);
                cmd
            }
        }
    };

    cmd.current_dir(workdir)
        .env("RUST_BACKTRACE", "1")
        .args(bench.args.as_slice());

    cmd.output()
        .expect(&format!("Failed to execute benchmark '{}'!", bench.name))
}

fn write_output(output: &Output, commit_id: git2::Oid, name: &str) {
    use std::fs::File;
    use std::io::Write;

    let mut stdout_file =
        File::create(&format!("{}-{}-stdout.log", commit_id, name)).expect(&format!(
            "Failed to create stdout log file for '{}' at commit '{}'.",
            name, commit_id
        ));
    stdout_file
        .write_all(output.stdout.as_slice())
        .expect("Failed to write output to stdout log file!");
    let mut stderr_file =
        File::create(&format!("{}-{}-stderr.log", commit_id, name)).expect(&format!(
            "Failed to create stderr log file for '{}' at commit '{}'.",
            name, commit_id
        ));
    stderr_file
        .write_all(output.stderr.as_slice())
        .expect("Failed to write output to stderr log file!");
}

fn benchmark(
    workdir: &str,
    cfg: &Config,
    bench: &Benchmark,
    commit_id: git2::Oid,
    previous_result: Option<&HashMap<String, BenchmarkResult<f64>>>,
    timeout: Option<u64>,
) -> (ExitStatus, HashMap<String, BenchmarkResult<f64>>) {
    // Run the benchmark and collect its output
    let output = run_benchmark(workdir, cfg, bench, timeout);
    write_output(&output, commit_id, &bench.name);

    let lines = str::from_utf8(output.stdout.as_slice())
        .unwrap()
        .lines()
        .chain(str::from_utf8(output.stderr.as_slice()).unwrap().lines());
    let mut res = HashMap::new();

    // Don't try parsing the output if we didn't succeed
    if !output.status.success() {
        return (output.status, res);
    }

    // Success, so let's look for the results
    for l in lines {
        for (i, regex) in bench.result_expr.iter().enumerate() {
            for cap in regex.captures_iter(l) {
                let (metric, value) = if cap.len() > 2 {
                    (String::from(cap.at(1).unwrap()), cap.at(2))
                } else {
                    (format!("{}", i), cap.at(1))
                };
                let bm_name = format!("{}/{}", bench.name, &metric);
                if let Some(c) = value {
                    use std::str::FromStr;
                    let val = match f64::from_str(&c) {
                        Ok(f) => f,
                        Err(_) => {
                            println!(
                                "failed to parse value '{}' for {} into f64 number, ignoring",
                                c, bm_name
                            );
                            continue;
                        }
                    };
                    let new_result = match previous_result {
                        None => BenchmarkResult::Improvement(val, 0.0),
                        Some(prev_res) => {
                            let old_val = match prev_res.get(&bm_name) {
                                None => val,
                                Some(pv) => match *pv {
                                    BenchmarkResult::Improvement(v, _) => v,
                                    BenchmarkResult::Regression(v, _) => v,
                                    BenchmarkResult::Neutral(v, _) => v,
                                },
                            };
                            let new_result = if bench.lower_is_better {
                                if val >= old_val * (1.0 + bench.regression_threshold) {
                                    BenchmarkResult::Regression(val, (val / old_val) - 1.0)
                                } else if val < old_val * (1.0 - bench.improvement_threshold) {
                                    BenchmarkResult::Improvement(val, (val / old_val) - 1.0)
                                } else {
                                    BenchmarkResult::Neutral(val, (val / old_val) - 1.0)
                                }
                            } else {
                                if val >= old_val * (1.0 + bench.improvement_threshold) {
                                    BenchmarkResult::Improvement(val, (val / old_val) - 1.0)
                                } else if val < old_val * (1.0 - bench.regression_threshold) {
                                    BenchmarkResult::Regression(val, (val / old_val) - 1.0)
                                } else {
                                    BenchmarkResult::Neutral(val, (val / old_val) - 1.0)
                                }
                            };
                            new_result
                        }
                    };
                    res.insert(bm_name, new_result);
                }
            }
        }
    }
    (output.status, res)
}

fn build(workdir: &str) -> Output {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("check")
        .arg("--all")
        .arg("--all-targets")
        .env("RUST_BACKTRACE", "1")
        .output()
        .expect("Failed to execute 'cargo build'!")
}

pub fn taste_commit(
    ws: &Workspace,
    history: &mut HashMap<String, HashMap<String, HashMap<String, BenchmarkResult<f64>>>>,
    push: &Push,
    commit: &Commit,
    def_improvement_threshold: f64,
    def_regression_threshold: f64,
    timeout: Option<u64>,
) -> Result<(Option<Config>, TastingResult), String> {
    println!("Tasting commit {}", commit.id);
    ws.checkout_commit(&commit.id)?;

    let branch = match push.push_ref {
        None => None,
        Some(ref pr) => match pr.rfind("/") {
            None => None,
            Some(i) => Some(String::from(&pr[i + 1..])),
        },
    };

    let do_update = !Path::new(&format!("{}/Cargo.lock", ws.path)).exists();

    let build_success = {
        let update_success = if do_update {
            println!("running 'cargo update'");
            let update_output = update(&ws.path);
            if !update_output.status.success() {
                println!("update failed: output status is {:?}", update_output.status);
            }
            update_output.status.success()
        } else {
            // nothing to do, always succeeds
            true
        };

        let build_output = build(&ws.path);
        write_output(&build_output, commit.id, "build");
        if !build_output.status.success() {
            println!("build failed: output status is {:?}", build_output.status);
        }

        update_success && build_output.status.success()
    };

    let test_output = test(&ws.path, timeout);
    write_output(&test_output, commit.id, "test");

    if !test_output.status.success() {
        println!("tests failed: output status is {:?}", test_output.status);
    }

    let cfg = match parse_config(
        Path::new(&format!("{}/taster.toml", ws.path)),
        def_improvement_threshold,
        def_regression_threshold,
    ) {
        Ok(c) => c,
        Err(e) => match e.kind() {
            io::ErrorKind::NotFound => {
                println!(
                    "Skipping commit {} which doesn't have a Taster config.",
                    commit.id
                );
                return Ok((
                    None,
                    TastingResult {
                        branch: branch,
                        commit: commit.clone(),
                        build: build_success,
                        test: test_output.status.success(),
                        bench: false,
                        results: None,
                    },
                ));
            }
            io::ErrorKind::InvalidInput => {
                println!(
                    "Skipping commit {} which has an invalid Taster config.",
                    commit.id
                );
                return Ok((
                    None,
                    TastingResult {
                        branch: branch,
                        commit: commit.clone(),
                        build: build_success,
                        test: test_output.status.success(),
                        bench: false,
                        results: None,
                    },
                ));
            }
            _ => unimplemented!(),
        },
    };

    let bench_results =
        match branch {
            Some(ref branch) => {
                let branch_history = history.entry(branch.clone()).or_insert(HashMap::new());
                cfg.benchmarks
                .iter()
                .map(|b| {
                    let (status, res) =
                        benchmark(&ws.path, &cfg, b, commit.id, branch_history.get(&b.name),
                                  timeout);
                    branch_history.insert(b.name.clone(), res.clone());
                    (b.clone(), status, res)
                })
                .collect::<Vec<(Benchmark, ExitStatus, HashMap<String, BenchmarkResult<f64>>)>>()
            }
            None => cfg.benchmarks
                .iter()
                .map(|b| {
                    let (status, res) = benchmark(&ws.path, &cfg, b, commit.id, None, timeout);
                    (b.clone(), status, res)
                })
                .collect::<Vec<(Benchmark, ExitStatus, HashMap<String, BenchmarkResult<f64>>)>>(),
        };
    let bench_success = bench_results.iter().all(|x| x.1.success());

    Ok((
        Some(cfg),
        TastingResult {
            branch: branch,
            commit: commit.clone(),
            build: build_success,
            test: test_output.status.success(),
            bench: bench_success,
            results: Some(bench_results),
        },
    ))
}

fn test(workdir: &str, timeout: Option<u64>) -> Output {
    let mut cmd = match timeout {
        None => {
            let mut cmd = Command::new("cargo");
            cmd.arg("test").arg("--all");
            cmd
        }
        Some(timeout) => {
            let mut cmd = Command::new("timeout");
            cmd.arg("-k")
                .arg(&format!("{}s", timeout + 30))
                .arg(&format!("{}s", timeout))
                .arg("cargo")
                .arg("test")
                .arg("--all");
            cmd
        }
    };
    cmd.current_dir(workdir)
        .env("RUST_BACKTRACE", "1")
        .env("RUST_TEST_THREADS", "1")
        .output()
        .expect("Failed to execute 'cargo test'!")
}

fn update(workdir: &str) -> Output {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("update")
        .output()
        .expect("Failed to execute 'cargo update'!")
}
<commit_msg>Log compiler version and cargo update results<commit_after>use config::{parse_config, Benchmark, Config};
use Commit;
use git2;
use Push;
use repo::Workspace;

use std::collections::HashMap;
use std::io;
use std::path::Path;
use std::process::{Command, ExitStatus, Output};
use std::str;

/// `(val, percentage_change)`
#[derive(Debug, Clone)]
pub enum BenchmarkResult<T> {
    Improvement(T, f64),
    Regression(T, f64),
    Neutral(T, f64),
}

#[derive(Debug, Clone)]
pub struct TastingResult {
    pub branch: Option<String>,
    pub commit: Commit,
    pub build: bool,
    pub test: bool,
    pub bench: bool,
    pub results: Option<Vec<(Benchmark, ExitStatus, HashMap<String, BenchmarkResult<f64>>)>>,
}

fn run_benchmark(workdir: &str, cfg: &Config, bench: &Benchmark, timeout: Option<u64>) -> Output {
    let mut cmd = if cfg.version.is_none() || cfg.version.unwrap() < 2 {
        // older taster configs assume an implied "cargo" prefix on each benchmark command
        match timeout {
            None => {
                let mut cmd = Command::new("cargo");
                cmd.arg(&bench.cmd);
                cmd
            }
            Some(timeout) => {
                let mut cmd = Command::new("timeout");
                cmd.arg("-k")
                    .arg(&format!("{}s", timeout + 30))
                    .arg(&format!("{}s", timeout))
                    .arg("cargo")
                    .arg(&bench.cmd);
                cmd
            }
        }
    } else {
        // from taster config version 2, we no longer assume an implicit "cargo" prefix on
        // benchmark commands
        match timeout {
            None => Command::new(&bench.cmd),
            Some(timeout) => {
                let mut cmd = Command::new("timeout");
                cmd.arg("-k")
                    .arg(&format!("{}s", timeout + 30))
                    .arg(&format!("{}s", timeout))
                    .arg(&bench.cmd);
                cmd
            }
        }
    };

    cmd.current_dir(workdir)
        .env("RUST_BACKTRACE", "1")
        .args(bench.args.as_slice());

    cmd.output()
        .expect(&format!("Failed to execute benchmark '{}'!", bench.name))
}

fn write_output(output: &Output, commit_id: git2::Oid, name: &str) {
    use std::fs::File;
    use std::io::Write;

    let mut stdout_file =
        File::create(&format!("{}-{}-stdout.log", commit_id, name)).expect(&format!(
            "Failed to create stdout log file for '{}' at commit '{}'.",
            name, commit_id
        ));
    stdout_file
        .write_all(output.stdout.as_slice())
        .expect("Failed to write output to stdout log file!");
    let mut stderr_file =
        File::create(&format!("{}-{}-stderr.log", commit_id, name)).expect(&format!(
            "Failed to create stderr log file for '{}' at commit '{}'.",
            name, commit_id
        ));
    stderr_file
        .write_all(output.stderr.as_slice())
        .expect("Failed to write output to stderr log file!");
}

fn benchmark(
    workdir: &str,
    cfg: &Config,
    bench: &Benchmark,
    commit_id: git2::Oid,
    previous_result: Option<&HashMap<String, BenchmarkResult<f64>>>,
    timeout: Option<u64>,
) -> (ExitStatus, HashMap<String, BenchmarkResult<f64>>) {
    // Run the benchmark and collect its output
    let output = run_benchmark(workdir, cfg, bench, timeout);
    write_output(&output, commit_id, &bench.name);

    let lines = str::from_utf8(output.stdout.as_slice())
        .unwrap()
        .lines()
        .chain(str::from_utf8(output.stderr.as_slice()).unwrap().lines());
    let mut res = HashMap::new();

    // Don't try parsing the output if we didn't succeed
    if !output.status.success() {
        return (output.status, res);
    }

    // Success, so let's look for the results
    for l in lines {
        for (i, regex) in bench.result_expr.iter().enumerate() {
            for cap in regex.captures_iter(l) {
                let (metric, value) = if cap.len() > 2 {
                    (String::from(cap.at(1).unwrap()), cap.at(2))
                } else {
                    (format!("{}", i), cap.at(1))
                };
                let bm_name = format!("{}/{}", bench.name, &metric);
                if let Some(c) = value {
                    use std::str::FromStr;
                    let val = match f64::from_str(&c) {
                        Ok(f) => f,
                        Err(_) => {
                            println!(
                                "failed to parse value '{}' for {} into f64 number, ignoring",
                                c, bm_name
                            );
                            continue;
                        }
                    };
                    let new_result = match previous_result {
                        None => BenchmarkResult::Improvement(val, 0.0),
                        Some(prev_res) => {
                            let old_val = match prev_res.get(&bm_name) {
                                None => val,
                                Some(pv) => match *pv {
                                    BenchmarkResult::Improvement(v, _) => v,
                                    BenchmarkResult::Regression(v, _) => v,
                                    BenchmarkResult::Neutral(v, _) => v,
                                },
                            };
                            let new_result = if bench.lower_is_better {
                                if val >= old_val * (1.0 + bench.regression_threshold) {
                                    BenchmarkResult::Regression(val, (val / old_val) - 1.0)
                                } else if val < old_val * (1.0 - bench.improvement_threshold) {
                                    BenchmarkResult::Improvement(val, (val / old_val) - 1.0)
                                } else {
                                    BenchmarkResult::Neutral(val, (val / old_val) - 1.0)
                                }
                            } else {
                                if val >= old_val * (1.0 + bench.improvement_threshold) {
                                    BenchmarkResult::Improvement(val, (val / old_val) - 1.0)
                                } else if val < old_val * (1.0 - bench.regression_threshold) {
                                    BenchmarkResult::Regression(val, (val / old_val) - 1.0)
                                } else {
                                    BenchmarkResult::Neutral(val, (val / old_val) - 1.0)
                                }
                            };
                            new_result
                        }
                    };
                    res.insert(bm_name, new_result);
                }
            }
        }
    }
    (output.status, res)
}

fn build(workdir: &str) -> Output {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("check")
        .arg("--all")
        .arg("--all-targets")
        .env("RUST_BACKTRACE", "1")
        .output()
        .expect("Failed to execute 'cargo build'!")
}

pub fn taste_commit(
    ws: &Workspace,
    history: &mut HashMap<String, HashMap<String, HashMap<String, BenchmarkResult<f64>>>>,
    push: &Push,
    commit: &Commit,
    def_improvement_threshold: f64,
    def_regression_threshold: f64,
    timeout: Option<u64>,
) -> Result<(Option<Config>, TastingResult), String> {
    println!("Tasting commit {}", commit.id);
    ws.checkout_commit(&commit.id)?;

    let branch = match push.push_ref {
        None => None,
        Some(ref pr) => match pr.rfind("/") {
            None => None,
            Some(i) => Some(String::from(&pr[i + 1..])),
        },
    };

    let version_output = version(&ws.path);
    write_output(&version_output, commit.id, "version");

    let do_update = !Path::new(&format!("{}/Cargo.lock", ws.path)).exists();

    let build_success = {
        let update_success = if do_update {
            println!("running 'cargo update'");
            let update_output = update(&ws.path);
            write_output(&update_output, commit.id, "update");
            if !update_output.status.success() {
                println!("update failed: output status is {:?}", update_output.status);
            }
            update_output.status.success()
        } else {
            // nothing to do, always succeeds
            true
        };

        let build_output = build(&ws.path);
        write_output(&build_output, commit.id, "build");
        if !build_output.status.success() {
            println!("build failed: output status is {:?}", build_output.status);
        }

        update_success && build_output.status.success()
    };

    let test_output = test(&ws.path, timeout);
    write_output(&test_output, commit.id, "test");

    if !test_output.status.success() {
        println!("tests failed: output status is {:?}", test_output.status);
    }

    let cfg = match parse_config(
        Path::new(&format!("{}/taster.toml", ws.path)),
        def_improvement_threshold,
        def_regression_threshold,
    ) {
        Ok(c) => c,
        Err(e) => match e.kind() {
            io::ErrorKind::NotFound => {
                println!(
                    "Skipping commit {} which doesn't have a Taster config.",
                    commit.id
                );
                return Ok((
                    None,
                    TastingResult {
                        branch: branch,
                        commit: commit.clone(),
                        build: build_success,
                        test: test_output.status.success(),
                        bench: false,
                        results: None,
                    },
                ));
            }
            io::ErrorKind::InvalidInput => {
                println!(
                    "Skipping commit {} which has an invalid Taster config.",
                    commit.id
                );
                return Ok((
                    None,
                    TastingResult {
                        branch: branch,
                        commit: commit.clone(),
                        build: build_success,
                        test: test_output.status.success(),
                        bench: false,
                        results: None,
                    },
                ));
            }
            _ => unimplemented!(),
        },
    };

    let bench_results =
        match branch {
            Some(ref branch) => {
                let branch_history = history.entry(branch.clone()).or_insert(HashMap::new());
                cfg.benchmarks
                .iter()
                .map(|b| {
                    let (status, res) =
                        benchmark(&ws.path, &cfg, b, commit.id, branch_history.get(&b.name),
                                  timeout);
                    branch_history.insert(b.name.clone(), res.clone());
                    (b.clone(), status, res)
                })
                .collect::<Vec<(Benchmark, ExitStatus, HashMap<String, BenchmarkResult<f64>>)>>()
            }
            None => cfg.benchmarks
                .iter()
                .map(|b| {
                    let (status, res) = benchmark(&ws.path, &cfg, b, commit.id, None, timeout);
                    (b.clone(), status, res)
                })
                .collect::<Vec<(Benchmark, ExitStatus, HashMap<String, BenchmarkResult<f64>>)>>(),
        };
    let bench_success = bench_results.iter().all(|x| x.1.success());

    Ok((
        Some(cfg),
        TastingResult {
            branch: branch,
            commit: commit.clone(),
            build: build_success,
            test: test_output.status.success(),
            bench: bench_success,
            results: Some(bench_results),
        },
    ))
}

fn test(workdir: &str, timeout: Option<u64>) -> Output {
    let mut cmd = match timeout {
        None => {
            let mut cmd = Command::new("cargo");
            cmd.arg("test").arg("--all");
            cmd
        }
        Some(timeout) => {
            let mut cmd = Command::new("timeout");
            cmd.arg("-k")
                .arg(&format!("{}s", timeout + 30))
                .arg(&format!("{}s", timeout))
                .arg("cargo")
                .arg("test")
                .arg("--all");
            cmd
        }
    };
    cmd.current_dir(workdir)
        .env("RUST_BACKTRACE", "1")
        .env("RUST_TEST_THREADS", "1")
        .output()
        .expect("Failed to execute 'cargo test'!")
}

fn update(workdir: &str) -> Output {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("update")
        .output()
        .expect("Failed to execute 'cargo update'!")
}

fn version(workdir: &str) -> Output {
    Command::new("rustc")
        .current_dir(workdir)
        .arg("--version")
        .output()
        .expect("Failed to execute 'rustc --version'!")
}
<|endoftext|>


<commit_before>use typenum::consts::{U0, U1, U2, U4};
use coordinates::{CoordinateSystem, Point};
use tensors::{Vector, Covector, Matrix, Tensor, ContravariantIndex, InnerProduct};
use generic_array::GenericArray;

struct Test2;
impl CoordinateSystem for Test2 {
    type Dimension = U2;
}

struct Test4;
impl CoordinateSystem for Test4 {
    type Dimension = U4;
}

#[test]
fn test_ranks() {
    assert_eq!(Vector::<Test4>::get_rank(), 1);
    assert_eq!(Matrix::<Test4>::get_rank(), 2);
}

#[test]
fn test_num_coords() {
    assert_eq!(Vector::<Test4>::get_num_coords(), 4);
    assert_eq!(Matrix::<Test4>::get_num_coords(), 16);
}

#[test]
fn test_iter_coords() {
    let p1 = Point::new(GenericArray::new());
    let matrix1 = Matrix::<Test2>::new(p1);
    let p2 = Point::new(GenericArray::new());
    let matrix2 = Matrix::<Test4>::new(p2);

    let mut i = 0;
    for _ in matrix1.iter_coords() {
        i += 1;
    }
    assert_eq!(i, 4);

    i = 0;
    for _ in matrix2.iter_coords() {
        i += 1;
    }
    assert_eq!(i, 16);
}

#[test]
fn test_add() {
    let p = Point::new(GenericArray::new());
    let mut vector1 = Vector::<Test2>::new(p);
    let mut vector2 = Vector::<Test2>::new(p);

    vector1[0] = 1.0;
    vector1[1] = 2.0;

    vector2[0] = 1.5;
    vector2[1] = 1.6;

    let result = vector1 + vector2;

    assert_eq!(result[0], 2.5);
    assert_eq!(result[1], 3.6);
}

#[test]
fn test_sub() {
    let p = Point::new(GenericArray::new());
    let mut vector1 = Vector::<Test2>::new(p);
    let mut vector2 = Vector::<Test2>::new(p);

    vector1[0] = 1.0;
    vector1[1] = 2.0;

    vector2[0] = 1.5;
    vector2[1] = 1.75;

    let result = vector1 - vector2;

    assert_eq!(result[0], -0.5);
    assert_eq!(result[1], 0.25);
}

#[test]
fn test_trace() {
    let p = Point::new(GenericArray::new());
    let mut matrix = Matrix::<Test2>::new(p);

    matrix[0] = 1.0;
    matrix[1] = 3.0;
    matrix[2] = 0.0;
    matrix[3] = 3.0;

    let tr = matrix.trace::<U0, U1>();

    assert_eq!(*tr, 4.0);
}

// needed for tests below
use std::ops::Mul;

#[test]
fn test_mul_trait() {
    assert_eq!(<Vector<Test2> as Mul<Vector<Test2>>>::Output::get_rank(), 2);
    assert_eq!(<Vector<Test2> as Mul<Vector<Test2>>>::Output::get_num_coords(), 4);
    assert_eq!(<Vector<Test2> as Mul<f64>>::Output::get_rank(), 1);
    assert_eq!(<Vector<Test2> as Mul<f64>>::Output::get_num_coords(), 2);
}

#[test]
fn test_mul_scalar() {
    let p = Point::new(GenericArray::new());
    let mut vector1 = Vector::<Test2>::new(p);

    vector1[0] = 1.0;
    vector1[1] = 2.0;

    // this works
    let result: Vector<Test2> = <Vector<Test2> as Mul<f64>>::mul(vector1, 5.0);
    // this doesn't
    // let result: Vector<Test2> = vector1 * 5.0;

    assert_eq!(result[0], 5.0);
    assert_eq!(result[1], 10.0);
}

#[test]
fn test_mul_vector() {
    let p = Point::new(GenericArray::new());
    let mut vector1 = Vector::<Test2>::new(p);
    let mut vector2 = Vector::<Test2>::new(p);

    vector1[0] = 1.0;
    vector1[1] = 2.0;

    vector2[0] = 3.0;
    vector2[1] = 4.0;

    // this works
    let result: Tensor<Test2, (ContravariantIndex, ContravariantIndex)> = <Vector<Test2> as Mul<Vector<Test2>>>::mul(vector1, vector2);
    // this doesn't
    // let result = vector1 * vector2;

    assert_eq!(result[0], 3.0);
    assert_eq!(result[1], 4.0);
    assert_eq!(result[2], 6.0);
    assert_eq!(result[3], 8.0);
}

#[test]
fn test_inner_product() {
    let p = Point::new(GenericArray::new());
    let mut vector1 = Vector::<Test2>::new(p);
    let mut vector2 = Covector::<Test2>::new(p);

    vector1[0] = 1.0;
    vector1[1] = 2.0;

    vector2[0] = 3.0;
    vector2[1] = 4.0;

    let result: Tensor<Test2, ()> = <Vector<Test2> as InnerProduct<Covector<Test2>, U0, U1>>::inner_product(vector1, vector2);

    assert_eq!(*result, 11.0);
}
<commit_msg>Added tests for matrix transposition and inversion<commit_after>use typenum::consts::{U0, U1, U2, U4};
use coordinates::{CoordinateSystem, Point};
use tensors::{Vector, Covector, Matrix, Tensor, ContravariantIndex, InnerProduct};
use generic_array::GenericArray;

struct Test2;
impl CoordinateSystem for Test2 {
    type Dimension = U2;
}

struct Test4;
impl CoordinateSystem for Test4 {
    type Dimension = U4;
}

#[test]
fn test_ranks() {
    assert_eq!(Vector::<Test4>::get_rank(), 1);
    assert_eq!(Matrix::<Test4>::get_rank(), 2);
}

#[test]
fn test_num_coords() {
    assert_eq!(Vector::<Test4>::get_num_coords(), 4);
    assert_eq!(Matrix::<Test4>::get_num_coords(), 16);
}

#[test]
fn test_iter_coords() {
    let p1 = Point::new(GenericArray::new());
    let matrix1 = Matrix::<Test2>::new(p1);
    let p2 = Point::new(GenericArray::new());
    let matrix2 = Matrix::<Test4>::new(p2);

    let mut i = 0;
    for _ in matrix1.iter_coords() {
        i += 1;
    }
    assert_eq!(i, 4);

    i = 0;
    for _ in matrix2.iter_coords() {
        i += 1;
    }
    assert_eq!(i, 16);
}

#[test]
fn test_add() {
    let p = Point::new(GenericArray::new());
    let mut vector1 = Vector::<Test2>::new(p);
    let mut vector2 = Vector::<Test2>::new(p);

    vector1[0] = 1.0;
    vector1[1] = 2.0;

    vector2[0] = 1.5;
    vector2[1] = 1.6;

    let result = vector1 + vector2;

    assert_eq!(result[0], 2.5);
    assert_eq!(result[1], 3.6);
}

#[test]
fn test_sub() {
    let p = Point::new(GenericArray::new());
    let mut vector1 = Vector::<Test2>::new(p);
    let mut vector2 = Vector::<Test2>::new(p);

    vector1[0] = 1.0;
    vector1[1] = 2.0;

    vector2[0] = 1.5;
    vector2[1] = 1.75;

    let result = vector1 - vector2;

    assert_eq!(result[0], -0.5);
    assert_eq!(result[1], 0.25);
}

#[test]
fn test_trace() {
    let p = Point::new(GenericArray::new());
    let mut matrix = Matrix::<Test2>::new(p);

    matrix[0] = 1.0;
    matrix[1] = 3.0;
    matrix[2] = 0.0;
    matrix[3] = 3.0;

    let tr = matrix.trace::<U0, U1>();

    assert_eq!(*tr, 4.0);
}

// needed for tests below
use std::ops::Mul;

#[test]
fn test_mul_trait() {
    assert_eq!(<Vector<Test2> as Mul<Vector<Test2>>>::Output::get_rank(), 2);
    assert_eq!(<Vector<Test2> as Mul<Vector<Test2>>>::Output::get_num_coords(), 4);
    assert_eq!(<Vector<Test2> as Mul<f64>>::Output::get_rank(), 1);
    assert_eq!(<Vector<Test2> as Mul<f64>>::Output::get_num_coords(), 2);
}

#[test]
fn test_mul_scalar() {
    let p = Point::new(GenericArray::new());
    let mut vector1 = Vector::<Test2>::new(p);

    vector1[0] = 1.0;
    vector1[1] = 2.0;

    // this works
    let result: Vector<Test2> = <Vector<Test2> as Mul<f64>>::mul(vector1, 5.0);
    // this doesn't
    // let result: Vector<Test2> = vector1 * 5.0;

    assert_eq!(result[0], 5.0);
    assert_eq!(result[1], 10.0);
}

#[test]
fn test_mul_vector() {
    let p = Point::new(GenericArray::new());
    let mut vector1 = Vector::<Test2>::new(p);
    let mut vector2 = Vector::<Test2>::new(p);

    vector1[0] = 1.0;
    vector1[1] = 2.0;

    vector2[0] = 3.0;
    vector2[1] = 4.0;

    // this works
    let result: Tensor<Test2, (ContravariantIndex, ContravariantIndex)> = <Vector<Test2> as Mul<Vector<Test2>>>::mul(vector1, vector2);
    // this doesn't
    // let result = vector1 * vector2;

    assert_eq!(result[0], 3.0);
    assert_eq!(result[1], 4.0);
    assert_eq!(result[2], 6.0);
    assert_eq!(result[3], 8.0);
}

#[test]
fn test_inner_product() {
    let p = Point::new(GenericArray::new());
    let mut vector1 = Vector::<Test2>::new(p);
    let mut vector2 = Covector::<Test2>::new(p);

    vector1[0] = 1.0;
    vector1[1] = 2.0;

    vector2[0] = 3.0;
    vector2[1] = 4.0;

    let result: Tensor<Test2, ()> = <Vector<Test2> as InnerProduct<Covector<Test2>, U0, U1>>::inner_product(vector1, vector2);

    assert_eq!(*result, 11.0);
}

#[test]
fn test_transpose() {
    let p = Point::new(GenericArray::new());
    let mut matrix = Matrix::<Test2>::new(p);

    matrix[0] = 1.0;
    matrix[1] = 2.0;
    matrix[2] = 3.0;
    matrix[3] = 4.0;

    let result = matrix.transpose();

    assert_eq!(result[0], 1.0);
    assert_eq!(result[1], 3.0);
    assert_eq!(result[2], 2.0);
    assert_eq!(result[3], 4.0);
}

#[test]
fn test_inverse() {
    let p = Point::new(GenericArray::new());
    let mut matrix = Matrix::<Test2>::new(p);

    matrix[0] = 1.0;
    matrix[1] = 2.0;
    matrix[2] = 3.0;
    matrix[3] = 4.0;

    let result = matrix.inverse().unwrap();

    // unfortunately the inverse matrix calculation isn't perfectly accurate
    let epsilon = 0.0000001;

    assert!((result[0] + 2.0).abs() < epsilon);
    assert!((result[1] - 1.0).abs() < epsilon);
    assert!((result[2] - 1.5).abs() < epsilon);
    assert!((result[3] + 0.5).abs() < epsilon);
}<|endoftext|>


<commit_before>extern crate collections;

use soundex::Soundex;

mod soundex;

fn check_soundex(word: ~str, expected: ~str) {
    let soundex = Soundex::new();
    assert_eq!(soundex.encode(word), expected);
}

#[test]
fn soundex_encoding_retains_sole_letter_of_one_letter_word() {
    check_soundex(~"A", ~"A000");
}

#[test]
fn soundex_encoding_pads_with_zeros_to_ensure_three_digits() {
    check_soundex(~"I", ~"I000");
}

#[test]
fn soundex_encoding_replaces_constants_with_appropriate_digits() {
    check_soundex(~"Ax", ~"A200");
}

#[test]
fn soundex_encoding_ignores_non_alphabetics() {
    check_soundex(~"A#", ~"A000");
}

#[test]
fn soundex_encoding_replaces_multiple_consonants_with_digits() {
    check_soundex(~"Acdl", ~"A234");
}

#[test]
fn soundex_encoding_limits_length_to_four_characters() {
    let soundex = Soundex::new();
    assert_eq!(soundex.encode("Dcdlb").len(), 4);
}

#[test]
fn soundex_encoding_ignores_vowel_like_letters() {
   check_soundex(~"Baeiouhycdl", ~"B234");
}

#[test]
fn soundex_encoding_combines_duplicate_encodings() {
   assert_eq!(soundex::encoded_digit('b'), soundex::encoded_digit('f'));
   assert_eq!(soundex::encoded_digit('c'), soundex::encoded_digit('g'));
   assert_eq!(soundex::encoded_digit('d'), soundex::encoded_digit('t'));
   check_soundex(~"Abfcgdt", ~"A123");
}

#[test]
fn soundex_encoding_uppercases_first_letter() {
    let soundex = Soundex::new();
    assert_eq!(soundex.encode("abcd").slice_to(1).to_owned(), ~"A");
}
<commit_msg>Test ignored vowels also works with uppercase vowels.<commit_after>extern crate collections;

use soundex::Soundex;

mod soundex;

fn check_soundex(word: ~str, expected: ~str) {
    let soundex = Soundex::new();
    assert_eq!(soundex.encode(word), expected);
}

#[test]
fn soundex_encoding_retains_sole_letter_of_one_letter_word() {
    check_soundex(~"A", ~"A000");
}

#[test]
fn soundex_encoding_pads_with_zeros_to_ensure_three_digits() {
    check_soundex(~"I", ~"I000");
}

#[test]
fn soundex_encoding_replaces_constants_with_appropriate_digits() {
    check_soundex(~"Ax", ~"A200");
}

#[test]
fn soundex_encoding_ignores_non_alphabetics() {
    check_soundex(~"A#", ~"A000");
}

#[test]
fn soundex_encoding_replaces_multiple_consonants_with_digits() {
    check_soundex(~"Acdl", ~"A234");
}

#[test]
fn soundex_encoding_limits_length_to_four_characters() {
    let soundex = Soundex::new();
    assert_eq!(soundex.encode("Dcdlb").len(), 4);
}

#[test]
fn soundex_encoding_ignores_vowel_like_letters() {
   check_soundex(~"BaAeEiIoOuUhHyYcdl", ~"B234");
}

#[test]
fn soundex_encoding_combines_duplicate_encodings() {
   assert_eq!(soundex::encoded_digit('b'), soundex::encoded_digit('f'));
   assert_eq!(soundex::encoded_digit('c'), soundex::encoded_digit('g'));
   assert_eq!(soundex::encoded_digit('d'), soundex::encoded_digit('t'));
   check_soundex(~"Abfcgdt", ~"A123");
}

#[test]
fn soundex_encoding_uppercases_first_letter() {
    let soundex = Soundex::new();
    assert_eq!(soundex.encode("abcd").slice_to(1).to_owned(), ~"A");
}
<|endoftext|>


<commit_before>use super::*;
use std::env;
use error::Error;
use error::api::Errcode;

const ENV_KEY: &str = "PROXER_API_KEY";

#[test]
fn api_response() {
	// is the api structured as we want it to be?
	let client = mk_client();

	let res = client.api().info().get_fullentry(parameter::InfoGetFullEntry {
		id: 53
	}).send();

	println!();

	match res {
		Err(e) => {
			match e {
				Error::Api(e) => {
					match e.error() {
						Errcode::NoApiPermissions => return,
						_ => panic!("this error is not expected"),
					}
				},
				Error::Json => panic!("can't parse json"),
				Error::Unknown => panic!("unknown error"),
				_ => return,
			}
		},

		Ok(r) => {
			assert_eq!(r.medium, "animeseries");
		}
	}
}

fn mk_client() -> Client {
	let api_key = match env::var_os(ENV_KEY) {
		Some(r) => r,
		// using a dummy key
		None => "DUMMY".into()
	};

	Client::new(api_key.into_string().unwrap())
}
<commit_msg>use new constructor method. see 04c6d46<commit_after>use super::*;
use std::env;

const ENV_KEY: &str = "PROXER_API_KEY";

#[test]
fn api_response() {
	// is the api structured as we want it to be?
	let client =  Client::with_env_key(ENV_KEY).unwrap();

	let res = client.api().info().get_fullentry(parameter::InfoGetFullEntry {
		id: 53
	}).send();

	println!();

	match res {
		Err(e) => {
			match e {
				error::Error::Api(e) => {
					match e.error() {
						error::api::Errcode::NoApiPermissions => return,
						_ => panic!("this error is not expected"),
					}
				},
				error::Error::Json => panic!("can't parse json"),
				error::Error::Unknown => panic!("unknown error"),
				_ => return,
			}
		},

		Ok(r) => {
			assert_eq!(r.medium, "animeseries");
		}
	}
}
<|endoftext|>


<commit_before>//! Some unit tests for all the internal functionality of lrs

#[cfg(test)]
#[allow(dead_code)]
#[allow(unused_macros)]
#[allow(unused_imports)]
mod tests {
    use terms::*;
    use clause::*;
    use result::*;

    #[test]
     fn lrs_symbol_create() {
        let s = symbol!["A"];
        assert!(s.val == 'A');
        assert!(s.state == true);
    }

    #[test]
    fn lrs_term_create() {
        let term = term!["A", "!🐎", "🍝", "!📰"];

        assert!(term.contains(&symbol!["A"]));
        assert!(term.contains(&symbol!["!🐎"]));
        assert!(term.contains(&symbol!["🍝"]));
        assert!(term.contains(&symbol!["!📰"]));
    }

    #[test]
    fn lrs_term_remove() {
        let mut term = term!["A", "!🐎", "🍝", "!📰"];

        term.remove(symbol!["A"]);
        assert!(! term.contains(&symbol!["A"]));

        term.remove(symbol!["!🐎"]);
        assert!(! term.contains(&symbol!["!🐎"]));

        term.remove(symbol!["🍝"]);
        assert!(! term.contains(&symbol!["🍝"]));

        term.remove(symbol!["!📰"]);
        assert!(! term.contains(&symbol!["!📰"]));
    }

    #[test]
    fn lrs_compare_terms() {
        let a = term!["A", "B"];
        let b = term!["B", "C"];
        let clause = clause![a, b];

        assert!(clause.contains(&term!["A", "B"]));
        assert!(clause.contains(&term!["B", "A"]));

        assert!(clause.contains(&term!["C", "B"]));
        assert!(! clause.contains(&term!["C", "D"]));
    }

    #[test]
    fn lrs_compare_clauses() {
        let c1 = clause![term!["A"]];
        let c2 = clause![term!["A"]];
        assert_eq!(c1, c2);

        let c3 = clause![term!["A", "B"], term!["!B"]];
        let c4 = clause![term!["B", "A"], term!["!B"]];
        assert_eq!(c3, c4);

        let c5 = clause![term!["A", "B"], term!["B"]];
        let c6 = clause![term!["A"], term!["!B"]];
        assert!(c5 != c6);
    }

    #[test]
    fn lrs_simple_reduce1() {
        let a = term!["A", "!B"];
        let b = term!["C", "!D"];
        let c = term!["E"];

        let mut cl = clause![a, b, c];
        cl.reduce();

        /* We should no longer contain "E" */
        assert!(! cl.contains(&term!["E"]));
    }

    #[test]
    fn lrs_simple_reduce2() {
        let a = term!["A", "!B"];
        let b = term!["C", "!D"];
        let c = term!["E"];
        let d = term!["F"];

        let mut cl = clause![a.clone(), b.clone(), c, d];
        cl.reduce();
        cl.reduce();

        /* Should now look like {A, !B} & {C, !D} */
        assert_eq!(cl, clause![a, b]);
    }

    #[test]
    fn lrs_result_create() {
        let r = result![true, ("A", false), ("B", true)];
        assert_eq!(r.symbols.get(&symbol!["A"]).unwrap(), &false);
        assert_eq!(r.symbols.get(&symbol!["B"]).unwrap(), &true);
        assert_eq!(r.solvable, true);
    }

    // #[test]
    // fn lrs_merge_reduce_1() {
    //     let a1 = term!["A", "!B"];
    //     let b1 = term!["A", "B"];
    //     let c1 = term!["C", "!D"];

    //     let mut cl = clause![a1, b1, c1];
    //     cl.reduce();
    //     assert_eq!(cl, clause![term!["A"], term!["C", "!D"]]);
    // }

    // #[test]
    // fn lrs_merge_reduce_2() {

    //     /* ...Oh fuck this is a difficult one... */
    //     let a2 = term!["A", "!B"];
    //     let b2 = term!["A", "B"];
    //     let c2 = term!["!A", "D"];

    //     let mut cl = clause![a2, b2, c2];
    //     cl.reduce();
    //     cl.reduce();

    //     /* It needs to have picked a2 and b2 first 😟 */
    //     assert_eq!(cl, clause![term!["D"]]);
    // }
}
<commit_msg>Adjusting the result test<commit_after>//! Some unit tests for all the internal functionality of lrs

#[cfg(test)]
#[allow(dead_code)]
#[allow(unused_macros)]
#[allow(unused_imports)]
mod tests {
    use terms::*;
    use clause::*;
    use result::*;

    #[test]
     fn lrs_symbol_create() {
        let s = symbol!["A"];
        assert!(s.val == 'A');
        assert!(s.state == true);
    }

    #[test]
    fn lrs_term_create() {
        let term = term!["A", "!🐎", "🍝", "!📰"];

        assert!(term.contains(&symbol!["A"]));
        assert!(term.contains(&symbol!["!🐎"]));
        assert!(term.contains(&symbol!["🍝"]));
        assert!(term.contains(&symbol!["!📰"]));
    }

    #[test]
    fn lrs_term_remove() {
        let mut term = term!["A", "!🐎", "🍝", "!📰"];

        term.remove(symbol!["A"]);
        assert!(! term.contains(&symbol!["A"]));

        term.remove(symbol!["!🐎"]);
        assert!(! term.contains(&symbol!["!🐎"]));

        term.remove(symbol!["🍝"]);
        assert!(! term.contains(&symbol!["🍝"]));

        term.remove(symbol!["!📰"]);
        assert!(! term.contains(&symbol!["!📰"]));
    }

    #[test]
    fn lrs_compare_terms() {
        let a = term!["A", "B"];
        let b = term!["B", "C"];
        let clause = clause![a, b];

        assert!(clause.contains(&term!["A", "B"]));
        assert!(clause.contains(&term!["B", "A"]));

        assert!(clause.contains(&term!["C", "B"]));
        assert!(! clause.contains(&term!["C", "D"]));
    }

    #[test]
    fn lrs_compare_clauses() {
        let c1 = clause![term!["A"]];
        let c2 = clause![term!["A"]];
        assert_eq!(c1, c2);

        let c3 = clause![term!["A", "B"], term!["!B"]];
        let c4 = clause![term!["B", "A"], term!["!B"]];
        assert_eq!(c3, c4);

        let c5 = clause![term!["A", "B"], term!["B"]];
        let c6 = clause![term!["A"], term!["!B"]];
        assert!(c5 != c6);
    }

    #[test]
    fn lrs_simple_reduce1() {
        let a = term!["A", "!B"];
        let b = term!["C", "!D"];
        let c = term!["E"];

        let mut cl = clause![a, b, c];
        cl.reduce();

        /* We should no longer contain "E" */
        assert!(! cl.contains(&term!["E"]));
    }

    #[test]
    fn lrs_simple_reduce2() {
        let a = term!["A", "!B"];
        let b = term!["C", "!D"];
        let c = term!["E"];
        let d = term!["F"];

        let mut cl = clause![a.clone(), b.clone(), c, d];
        cl.reduce();
        cl.reduce();

        /* Should now look like {A, !B} & {C, !D} */
        assert_eq!(cl, clause![a, b]);
    }

    #[test]
    fn lrs_result_create() {
        let r = result![true, ("A", false), ("B", true)];
        assert_eq!(r.symbols.get(&symbol!["A"]).unwrap(), &false);
        assert_eq!(r.symbols.get(&symbol!["B"]).unwrap(), &true);
        assert_eq!(r.solvable, true);

        println!("{:?}", r);
    }

    // #[test]
    // fn lrs_merge_reduce_1() {
    //     let a1 = term!["A", "!B"];
    //     let b1 = term!["A", "B"];
    //     let c1 = term!["C", "!D"];

    //     let mut cl = clause![a1, b1, c1];
    //     cl.reduce();
    //     assert_eq!(cl, clause![term!["A"], term!["C", "!D"]]);
    // }

    // #[test]
    // fn lrs_merge_reduce_2() {

    //     /* ...Oh fuck this is a difficult one... */
    //     let a2 = term!["A", "!B"];
    //     let b2 = term!["A", "B"];
    //     let c2 = term!["!A", "D"];

    //     let mut cl = clause![a2, b2, c2];
    //     cl.reduce();
    //     cl.reduce();

    //     /* It needs to have picked a2 and b2 first 😟 */
    //     assert_eq!(cl, clause![term!["D"]]);
    // }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{BufReader, Read};
use std::path::{Path, PathBuf};
use std::ffi::CString;

use rustc_llvm::archive_ro::ArchiveRO;
use cty::c_char;
use llvm;
use error::*;
use session::{Configuration, Output, Session};

pub struct Linker {
    session: Session,
    context: llvm::ContextRef,
    module: llvm::ModuleRef,
}

impl Linker {
    pub fn new(session: Session) -> Self {
        let module_name = CString::new("nvptx-module").unwrap();
        let context = unsafe { llvm::LLVMContextCreate() };

        Linker {
            session,
            context,
            module: unsafe {
                llvm::LLVMModuleCreateWithNameInContext(module_name.as_ptr(), context)
            },
        }
    }

    pub fn link(self) -> Result<()> {
        self.link_bitcode();
        self.link_rlibs();
        self.run_passes();

        unsafe {
            llvm::StripInternalFunctions(self.module);
            llvm::RenameGlobalVariables(self.module);

            let mut message = llvm::Message::new();
            if llvm::FindExternalReferences(self.module, &mut message) > 0 {
                let references: Vec<String> = message
                    .to_string()
                    .split(";")
                    .map(|name| String::from(name))
                    .collect();

                return Err(ErrorKind::UndefinedReferences(references).into());
            }
        }

        for output in &self.session.emit {
            match *output {
                Output::PTXAssembly => self.emit_asm().chain_err(|| "Unable to emit PTX assembly")?,
                Output::Bitcode => self.emit_bc().chain_err(|| "Unable to emit LLVM bitcode")?,
                Output::IntermediateRepresentation => {
                    self.emit_ir().chain_err(|| "Unable to emit LLVM IR code")?
                }
            }
        }

        Ok(())
    }

    fn link_bitcode(&self) {
        for module_path in &self.session.include_bitcode_modules {
            debug!("Linking bitcode: {:?}", module_path);

            let mut bitcode_file = BufReader::new(File::open(&module_path).unwrap());
            let mut bitcode_bytes = vec![];

            bitcode_file.read_to_end(&mut bitcode_bytes).unwrap();
            unsafe {
                // TODO: check result
                llvm::LLVMRustLinkInExternalBitcode(
                    self.module,
                    bitcode_bytes.as_ptr() as *const c_char,
                    bitcode_bytes.len(),
                );
            }
        }
    }

    fn link_rlibs(&self) {
        for rlib_path in &self.session.include_rlibs {
            debug!("Linking rlib: {:?}", rlib_path);

            let archive = ArchiveRO::open(rlib_path).unwrap();
            for item in archive.iter() {
                let name = Path::new(item.as_ref().unwrap().name().unwrap());

                if self.is_rlib_item_linkable(&name) {
                    debug!("  - linking archive item: {:?}", name);
                    let data = item.as_ref().unwrap().data();

                    unsafe {
                        // TODO: check result
                        llvm::LLVMRustLinkInExternalBitcode(
                            self.module,
                            data.as_ptr() as *const c_char,
                            data.len(),
                        );
                    }
                }
            }
        }
    }

    fn is_rlib_item_linkable(&self, name: &Path) -> bool {
        name.extension().unwrap() == "o"
    }

    fn run_passes(&self) {
        unsafe {
            let builder = llvm::LLVMPassManagerBuilderCreate();
            let pass_manager = llvm::LLVMCreatePassManager();

            match self.session.configuration {
                Configuration::Debug => {
                    info!("Linking without optimisations");
                    llvm::LLVMPassManagerBuilderSetOptLevel(builder, 0);
                }

                Configuration::Release => {
                    info!("Linking with Link Time Optimisation");
                    llvm::LLVMPassManagerBuilderSetOptLevel(builder, 3);
                    llvm::LLVMPassManagerBuilderPopulateLTOPassManager(
                        builder,
                        pass_manager,
                        llvm::True,
                        llvm::True,
                    );
                }
            }

            llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, pass_manager);
            llvm::LLVMPassManagerBuilderDispose(builder);

            llvm::LLVMRunPassManager(pass_manager, self.module);
            llvm::LLVMDisposePassManager(pass_manager);
        }
    }

    fn emit_ir(&self) -> Result<()> {
        let path = CString::new(self.get_output_path_with_ext("ll")?.to_str().unwrap()).unwrap();

        unsafe {
            // TODO: check result
            let mut message = llvm::Message::new();
            llvm::LLVMPrintModuleToFile(self.module, path.as_ptr(), &mut message);

            if !message.is_empty() {
                // TODO: stderr?
                println!("{}", message);
            }
        }

        info!("LLVM IR has been written to {:?}", path);
        Ok(())
    }

    fn emit_bc(&self) -> Result<()> {
        let path = CString::new(self.get_output_path_with_ext("bc")?.to_str().unwrap()).unwrap();

        unsafe {
            // TODO: check result
            llvm::LLVMWriteBitcodeToFile(self.module, path.as_ptr());
        }

        info!("LLVM bitcode has been written to {:?}", path);
        Ok(())
    }

    fn emit_asm(&self) -> Result<()> {
        let path = CString::new(self.get_output_path()?.to_str().unwrap()).unwrap();

        let cpu = CString::new("sm_20").unwrap();
        let feature = CString::new("").unwrap();

        unsafe {
            llvm::LLVMInitializeNVPTXTargetInfo();
            llvm::LLVMInitializeNVPTXTarget();
            llvm::LLVMInitializeNVPTXTargetMC();
            llvm::LLVMInitializeNVPTXAsmPrinter();

            let triple = llvm::LLVMGetTarget(self.module);
            let target = llvm::LLVMRustCreateTargetMachine(
                triple,
                cpu.as_ptr(),
                feature.as_ptr(),
                llvm::CodeModel::Default,
                llvm::RelocMode::Default,
                llvm::CodeGenOptLevel::Default,
                false,
                false,
                false,
                false,
                true,
                true,
            );

            // TODO: check `target` != nullptr

            // We need an empty pass manager only for LLVM to add "asm printer" pass.
            let emitting_pass_manager = llvm::LLVMCreatePassManager();

            // TODO: check result
            llvm::LLVMRustWriteOutputFile(
                target,
                emitting_pass_manager,
                self.module,
                path.as_ptr(),
                llvm::FileType::AssemblyFile,
            );

            llvm::LLVMRustDisposeTargetMachine(target);

            // We don't need to dispose `emiting_pass_manager` because Rust C api is already did this:
            // https://github.com/rust-lang/rust/blob/119066ff2bb39f7c8f7d1e68b7ad15e026f048e2/src/rustllvm/PassWrapper.cpp#L502
        }

        info!("PTX assembly has been written to {:?}", path);
        Ok(())
    }

    fn get_output_path(&self) -> Result<PathBuf> {
        match self.session.output.as_ref() {
            Some(path) => Ok(path.clone()),
            None => Err(ErrorKind::NoOutputPathError.into()),
        }
    }

    fn get_output_path_with_ext(&self, extension: &str) -> Result<PathBuf> {
        let mut output_path = self.get_output_path()?;
        output_path.set_extension(extension);

        Ok(output_path)
    }
}

impl Drop for Linker {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMDisposeModule(self.module);
            llvm::LLVMContextDispose(self.context);
        }
    }
}
<commit_msg>Adjust to latest nightly rust<commit_after>use std::fs::File;
use std::io::{BufReader, Read};
use std::path::{Path, PathBuf};
use std::ffi::CString;

use rustc_llvm::archive_ro::ArchiveRO;
use cty::c_char;
use llvm;
use error::*;
use session::{Configuration, Output, Session};

pub struct Linker {
    session: Session,
    context: llvm::ContextRef,
    module: llvm::ModuleRef,
}

impl Linker {
    pub fn new(session: Session) -> Self {
        let module_name = CString::new("nvptx-module").unwrap();
        let context = unsafe { llvm::LLVMRustContextCreate(false) };

        Linker {
            session,
            context,
            module: unsafe {
                llvm::LLVMModuleCreateWithNameInContext(module_name.as_ptr(), context)
            },
        }
    }

    pub fn link(self) -> Result<()> {
        self.link_bitcode();
        self.link_rlibs();
        self.run_passes();

        unsafe {
            llvm::StripInternalFunctions(self.module);
            llvm::RenameGlobalVariables(self.module);

            let mut message = llvm::Message::new();
            if llvm::FindExternalReferences(self.module, &mut message) > 0 {
                let references: Vec<String> = message
                    .to_string()
                    .split(";")
                    .map(|name| String::from(name))
                    .collect();

                return Err(ErrorKind::UndefinedReferences(references).into());
            }
        }

        for output in &self.session.emit {
            match *output {
                Output::PTXAssembly => self.emit_asm().chain_err(|| "Unable to emit PTX assembly")?,
                Output::Bitcode => self.emit_bc().chain_err(|| "Unable to emit LLVM bitcode")?,
                Output::IntermediateRepresentation => {
                    self.emit_ir().chain_err(|| "Unable to emit LLVM IR code")?
                }
            }
        }

        Ok(())
    }

    fn link_bitcode(&self) {
        for module_path in &self.session.include_bitcode_modules {
            debug!("Linking bitcode: {:?}", module_path);

            let mut bitcode_file = BufReader::new(File::open(&module_path).unwrap());
            let mut bitcode_bytes = vec![];

            bitcode_file.read_to_end(&mut bitcode_bytes).unwrap();
            unsafe {
                // TODO: check result
                llvm::LLVMRustLinkInExternalBitcode(
                    self.module,
                    bitcode_bytes.as_ptr() as *const c_char,
                    bitcode_bytes.len(),
                );
            }
        }
    }

    fn link_rlibs(&self) {
        for rlib_path in &self.session.include_rlibs {
            debug!("Linking rlib: {:?}", rlib_path);

            let archive = ArchiveRO::open(rlib_path).unwrap();
            for item in archive.iter() {
                let name = Path::new(item.as_ref().unwrap().name().unwrap());

                if self.is_rlib_item_linkable(&name) {
                    debug!("  - linking archive item: {:?}", name);
                    let data = item.as_ref().unwrap().data();

                    unsafe {
                        // TODO: check result
                        llvm::LLVMRustLinkInExternalBitcode(
                            self.module,
                            data.as_ptr() as *const c_char,
                            data.len(),
                        );
                    }
                }
            }
        }
    }

    fn is_rlib_item_linkable(&self, name: &Path) -> bool {
        name.extension().unwrap() == "o"
    }

    fn run_passes(&self) {
        unsafe {
            let builder = llvm::LLVMPassManagerBuilderCreate();
            let pass_manager = llvm::LLVMCreatePassManager();

            match self.session.configuration {
                Configuration::Debug => {
                    info!("Linking without optimisations");
                    llvm::LLVMPassManagerBuilderSetOptLevel(builder, 0);
                }

                Configuration::Release => {
                    info!("Linking with Link Time Optimisation");
                    llvm::LLVMPassManagerBuilderSetOptLevel(builder, 3);
                    llvm::LLVMPassManagerBuilderPopulateLTOPassManager(
                        builder,
                        pass_manager,
                        llvm::True,
                        llvm::True,
                    );
                }
            }

            llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, pass_manager);
            llvm::LLVMPassManagerBuilderDispose(builder);

            llvm::LLVMRunPassManager(pass_manager, self.module);
            llvm::LLVMDisposePassManager(pass_manager);
        }
    }

    fn emit_ir(&self) -> Result<()> {
        let path = CString::new(self.get_output_path_with_ext("ll")?.to_str().unwrap()).unwrap();

        unsafe {
            // TODO: check result
            let mut message = llvm::Message::new();
            llvm::LLVMPrintModuleToFile(self.module, path.as_ptr(), &mut message);

            if !message.is_empty() {
                // TODO: stderr?
                println!("{}", message);
            }
        }

        info!("LLVM IR has been written to {:?}", path);
        Ok(())
    }

    fn emit_bc(&self) -> Result<()> {
        let path = CString::new(self.get_output_path_with_ext("bc")?.to_str().unwrap()).unwrap();

        unsafe {
            // TODO: check result
            llvm::LLVMWriteBitcodeToFile(self.module, path.as_ptr());
        }

        info!("LLVM bitcode has been written to {:?}", path);
        Ok(())
    }

    fn emit_asm(&self) -> Result<()> {
        let path = CString::new(self.get_output_path()?.to_str().unwrap()).unwrap();

        let cpu = CString::new("sm_20").unwrap();
        let feature = CString::new("").unwrap();

        unsafe {
            llvm::LLVMInitializeNVPTXTargetInfo();
            llvm::LLVMInitializeNVPTXTarget();
            llvm::LLVMInitializeNVPTXTargetMC();
            llvm::LLVMInitializeNVPTXAsmPrinter();

            let triple = llvm::LLVMGetTarget(self.module);
            let target = llvm::LLVMRustCreateTargetMachine(
                triple,
                cpu.as_ptr(),
                feature.as_ptr(),
                llvm::CodeModel::Default,
                llvm::RelocMode::Default,
                llvm::CodeGenOptLevel::Default,
                false,
                false,
                false,
                false,
                true,
                true,
            );

            // TODO: check `target` != nullptr

            // We need an empty pass manager only for LLVM to add "asm printer" pass.
            let emitting_pass_manager = llvm::LLVMCreatePassManager();

            // TODO: check result
            llvm::LLVMRustWriteOutputFile(
                target,
                emitting_pass_manager,
                self.module,
                path.as_ptr(),
                llvm::FileType::AssemblyFile,
            );

            llvm::LLVMRustDisposeTargetMachine(target);

            // We don't need to dispose `emiting_pass_manager` because Rust C api is already did this:
            // https://github.com/rust-lang/rust/blob/119066ff2bb39f7c8f7d1e68b7ad15e026f048e2/src/rustllvm/PassWrapper.cpp#L502
        }

        info!("PTX assembly has been written to {:?}", path);
        Ok(())
    }

    fn get_output_path(&self) -> Result<PathBuf> {
        match self.session.output.as_ref() {
            Some(path) => Ok(path.clone()),
            None => Err(ErrorKind::NoOutputPathError.into()),
        }
    }

    fn get_output_path_with_ext(&self, extension: &str) -> Result<PathBuf> {
        let mut output_path = self.get_output_path()?;
        output_path.set_extension(extension);

        Ok(output_path)
    }
}

impl Drop for Linker {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMDisposeModule(self.module);
            llvm::LLVMContextDispose(self.context);
        }
    }
}
<|endoftext|>


<commit_before>/// Return early with an error.
///
/// This macro is equivalent to `return Err(From::from($err))`.
///
/// # Example
///
/// ```
/// # use anyhow::{bail, Result};
/// #
/// # fn has_permission(user: usize, resource: usize) -> bool {
/// #     true
/// # }
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #     let resource = 0;
/// #
/// if !has_permission(user, resource) {
///     bail!("permission denied for accessing {}", resource);
/// }
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{bail, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// if depth > MAX_DEPTH {
///     bail!(ScienceError::RecursionLimitExceeded);
/// }
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! bail {
    ($msg:literal $(,)?) => {
        return $crate::private::Err($crate::anyhow!($msg));
    };
    ($err:expr $(,)?) => {
        return $crate::private::Err($crate::anyhow!($err));
    };
    ($fmt:expr, $($arg:tt)*) => {
        return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
    };
}

/// Return early with an error if a condition is not satisfied.
///
/// This macro is equivalent to `if !$cond { return Err(From::from($err)); }`.
///
/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`
/// rather than panicking.
///
/// # Example
///
/// ```
/// # use anyhow::{ensure, Result};
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #
/// ensure!(user == 0, "only user 0 is allowed");
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{ensure, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! ensure {
    ($cond:expr, $msg:literal $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($msg));
        }
    };
    ($cond:expr, $err:expr $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($err));
        }
    };
    ($cond:expr, $fmt:expr, $($arg:tt)*) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
        }
    };
}

/// Construct an ad-hoc error from a string or existing non-`anyhow` error
/// value.
///
/// This evaluates to an `Error`. It can take either just a string, or a format
/// string with arguments. It also can take any custom type which implements
/// `Debug` and `Display`.
///
/// # Example
///
/// ```
/// # type V = ();
/// #
/// use anyhow::{anyhow, Result};
///
/// fn lookup(key: &str) -> Result<V> {
///     if key.len() != 16 {
///         return Err(anyhow!("key length must be 16 characters, got {:?}", key));
///     }
///
///     // ...
///     # Ok(())
/// }
/// ```
#[macro_export]
macro_rules! anyhow {
    ($msg:literal $(,)?) => {
        // Handle $:literal as a special case to make cargo-expanded code more
        // concise in the common case.
        $crate::private::new_adhoc($msg)
    };
    ($err:expr $(,)?) => ({
        use $crate::private::kind::*;
        let error = $err;
        (&error).anyhow_kind().new(error)
    });
    ($fmt:expr, $($arg:tt)*) => {
        $crate::private::new_adhoc(format!($fmt, $($arg)*))
    };
}
<commit_msg>Mention std::error::Error specialization behavior of `anyhow!`<commit_after>/// Return early with an error.
///
/// This macro is equivalent to `return Err(From::from($err))`.
///
/// # Example
///
/// ```
/// # use anyhow::{bail, Result};
/// #
/// # fn has_permission(user: usize, resource: usize) -> bool {
/// #     true
/// # }
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #     let resource = 0;
/// #
/// if !has_permission(user, resource) {
///     bail!("permission denied for accessing {}", resource);
/// }
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{bail, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// if depth > MAX_DEPTH {
///     bail!(ScienceError::RecursionLimitExceeded);
/// }
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! bail {
    ($msg:literal $(,)?) => {
        return $crate::private::Err($crate::anyhow!($msg));
    };
    ($err:expr $(,)?) => {
        return $crate::private::Err($crate::anyhow!($err));
    };
    ($fmt:expr, $($arg:tt)*) => {
        return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
    };
}

/// Return early with an error if a condition is not satisfied.
///
/// This macro is equivalent to `if !$cond { return Err(From::from($err)); }`.
///
/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`
/// rather than panicking.
///
/// # Example
///
/// ```
/// # use anyhow::{ensure, Result};
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #
/// ensure!(user == 0, "only user 0 is allowed");
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{ensure, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! ensure {
    ($cond:expr, $msg:literal $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($msg));
        }
    };
    ($cond:expr, $err:expr $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($err));
        }
    };
    ($cond:expr, $fmt:expr, $($arg:tt)*) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
        }
    };
}

/// Construct an ad-hoc error from a string or existing non-`anyhow` error
/// value.
///
/// This evaluates to an `Error`. It can take either just a string, or a format
/// string with arguments. It also can take any custom type which implements
/// `Debug` and `Display`.
///
/// If called with a single argument whose type implements `std::error::Error`
/// (in addition to `Debug` and `Display`, which are always required), then that
/// Error impl's `source` is preserved as the `source` of the resulting
/// `anyhow::Error`.
///
/// # Example
///
/// ```
/// # type V = ();
/// #
/// use anyhow::{anyhow, Result};
///
/// fn lookup(key: &str) -> Result<V> {
///     if key.len() != 16 {
///         return Err(anyhow!("key length must be 16 characters, got {:?}", key));
///     }
///
///     // ...
///     # Ok(())
/// }
/// ```
#[macro_export]
macro_rules! anyhow {
    ($msg:literal $(,)?) => {
        // Handle $:literal as a special case to make cargo-expanded code more
        // concise in the common case.
        $crate::private::new_adhoc($msg)
    };
    ($err:expr $(,)?) => ({
        use $crate::private::kind::*;
        let error = $err;
        (&error).anyhow_kind().new(error)
    });
    ($fmt:expr, $($arg:tt)*) => {
        $crate::private::new_adhoc(format!($fmt, $($arg)*))
    };
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! dense {
    ($elem:expr; $m:expr, $n:expr) => {
        $crate::DenseMatrix::from_vec(vec![$elem; $m*$n], $m, $n, None)
    };
    ($($($a:expr),+);+) => {
        $crate::DenseMatrix::new(&[$(vec![$(($a),)+],)+])
    };
}

#[macro_export]
macro_rules! eye {
    ($e:expr) => {
        $crate::IdentityMatrix::new($e)
    };
}

#[macro_export]
macro_rules! sparse {
    ($($tup:expr),+; $m:expr, $n:expr) => {
        $crate::SparseMatrix::from_tuple(vec![$($tup),+], $m, $n)
    };
}

#[macro_export]
macro_rules! zeros {
    ($m:expr, $n:expr) => {
        $crate::ZeroMatrix::new($m, $n)
    };
}
<commit_msg>Update macro variable for eye to make more sense in the context.<commit_after>#[macro_export]
macro_rules! dense {
    ($elem:expr; $m:expr, $n:expr) => {
        $crate::DenseMatrix::from_vec(vec![$elem; $m*$n], $m, $n, None)
    };
    ($($($a:expr),+);+) => {
        $crate::DenseMatrix::new(&[$(vec![$(($a),)+],)+])
    };
}

#[macro_export]
macro_rules! eye {
    ($n:expr) => {
        $crate::IdentityMatrix::new($n)
    };
}

#[macro_export]
macro_rules! sparse {
    ($($tup:expr),+; $m:expr, $n:expr) => {
        $crate::SparseMatrix::from_tuple(vec![$($tup),+], $m, $n)
    };
}

#[macro_export]
macro_rules! zeros {
    ($m:expr, $n:expr) => {
        $crate::ZeroMatrix::new($m, $n)
    };
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017-2019 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/// Connect events to sending a message.
///
/// ## Rules
/// 1. Send `$msg` to `$other_component` when the GTK+ `$event` is emitted on `$widget`.
///
/// 2. Optionally send `$msg.0` when the GTK+ `$event` is emitted on `$widget`.
/// Return `$msg.1` in the GTK+ callback.
/// This variant gives more control to the caller since it expects a `$msg` returning `(Option<MSG>,
/// ReturnValue)` where the `ReturnValue` is the value to return in the GTK+ callback.
/// Option<MSG> can be None if no message needs to be emitted.
///
/// 3. Send `$msg` when the GTK+ `$event` is emitted on `$widget`.
///
/// 4. Send `$msg` to `$widget` when the `$message` is received on `$stream`.
#[macro_export]
macro_rules! connect {
    // Connect to a GTK+ widget event, sending a message to another widget.
    ($widget:expr, $event:ident($($args:pat),*), $other_component:expr, $msg:expr) => {
        connect_stream!($widget, $event($($args),*), $other_component.stream(), $msg);
    };

    // Connect to a GTK+ widget event.
    // This variant gives more control to the caller since it expects a `$msg` returning (Option<MSG>,
    // ReturnValue) where the ReturnValue is the value to return in the GTK+ callback.
    // Option<MSG> can be None if no message needs to be emitted.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), return $msg:expr) => {{
        connect_stream!(return $relm.stream(), $widget, $event($($args),*), $msg);
    }};

    // Connect to a GTK+ widget event.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), $msg:expr) => {{
        let stream = $relm.stream().clone();
        let _ = $widget.$event(move |$($args),*| {
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    }};

    // Connect to a message reception.
    // TODO: create another macro rule accepting multiple patterns.
    ($src_component:ident @ $message:pat, $dst_component:expr, $msg:expr) => {
        let stream = $src_component.stream().clone();
        connect_stream!(stream@$message, $dst_component.stream(), $msg);
    };
}

/// Connect events to sending a message.
/// Similar to `connect!` but wants a stream instead of a component.
///
/// ## Rules
/// 1. Send `$msg` to `$other_stream` when the GTK+ `$event` is emitted on `$widget`.
///
/// 2. Send `$msg` to `$widget` when the `$message` is received on `$stream`.
#[macro_export]
macro_rules! connect_stream {
    // Connect to a GTK+ widget event.
    // This variant gives more control to the caller since it expects a `$msg` returning (Option<MSG>,
    // ReturnValue) where the ReturnValue is the value to return in the GTK+ callback.
    // Option<MSG> can be None if no message needs to be emitted.
    (return $stream:expr, $widget:expr, $event:ident($($args:pat),*), $msg:expr) => {{
        let stream = $stream.clone();
        let _ = $widget.$event(move |$($args),*| {
            let (msg, return_value) = $crate::IntoPair::into_pair($msg);
            let msg: Option<_> = $crate::IntoOption::into_option(msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
            return_value
        });
    }};

    // Connect to a GTK+ widget event, sending a message to another widget.
    ($widget:expr, $event:ident($($args:pat),*), $other_stream:expr, $msg:expr) => {
        let stream = $other_stream.clone();
        let _ = $widget.$event(move |$($args),*| {
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    };

    // Connect to a message reception.
    // TODO: create another macro rule accepting multiple patterns.
    ($src_stream:ident @ $message:pat, $dst_stream:expr, $msg:expr) => {
        let stream = $dst_stream.clone();
        $src_stream.observe(move |msg| {
            #[allow(unreachable_patterns)]
            match msg {
                &$message =>  {
                    let msg: Option<_> = $crate::IntoOption::into_option($msg);
                    if let Some(msg) = msg {
                        stream.emit(msg);
                    }
                },
                _ => (),
            }
        });
    };
}

/// Connect an asynchronous method call to send a message.
/// The variants with `$fail_msg` will send this message when there's an error.
/// Those without this argument will ignore the error.
#[macro_export]
macro_rules! connect_async {
    ($object:expr, $async_method:ident, $relm:expr, $msg:expr) => {
        connect_async!($object, $async_method(), $relm, $msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:expr) => {{
        // TODO: remove any use of Fragile when gio callbacks stop requiring Send.
        let stream = ::relm::vendor::fragile::Fragile::new($relm.stream().clone());
        $object.$async_method($($args,)* None, move |result| {
            if let Ok(result) = result {
                stream.into_inner().emit($msg(result));
            }
        });
    }};
    ($object:expr, $async_method:ident, $relm:expr, $msg:expr, $fail_msg:expr) => {
        connect_async!($object, $async_method(), $relm, $msg, $fail_msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:expr, $fail_msg:expr) => {{
        let event_stream = ::relm::vendor::fragile::Fragile::new($relm.stream().clone());
        let fail_event_stream = ::relm::vendor::fragile::Fragile::new($relm.stream().clone());
        $object.$async_method($($args,)* None, move |result| {
            match result.into_inner() {
                Ok(value) => event_stream.into_inner().emit($msg(value)),
                Err(error) => fail_event_stream.into_inner().emit($fail_msg(error)),
            }
        });
    }};
}

/// Connect an asynchronous function call to send a message.
/// The variants with `$fail_msg` will send this message when there's an error.
/// Those without this argument will ignore the error.
#[macro_export]
macro_rules! connect_async_func {
    ($class:ident :: $async_function:ident, $relm:expr, $msg:expr) => {
        connect_async_func!($class::$async_func(), $relm, $msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:expr) => {{
        let stream = ::relm::vendor::fragile::Fragile::new($relm.stream().clone());
        $class::$async_func($($args,)* None, move |result| {
            if let Ok(result) = result {
                stream.into_inner().emit($msg(result));
            }
        });
    }};
    ($class:ident :: $async_func:ident, $relm:expr, $msg:expr, $fail_msg:expr) => {
        connect_async_func!($class::$async_func(), $relm, $msg, $fail_msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:expr, $fail_msg:expr) => {{
        let event_stream = ::relm::vendor::fragile::Fragile::new($relm.stream().clone());
        let fail_event_stream = ::relm::vendor::fragile::Fragile::new($relm.stream().clone());
        $class::$async_func($($args,)* None, move |result| {
            match result {
                Ok(value) => event_stream.into_inner().emit($msg(value)),
                Err(error) => fail_event_stream.into_inner().emit($fail_msg(error)),
            }
        });

    }};
}

/// Like `connect_async!`, but also return a `Cancellable` to control the asynchronous request.
#[macro_export]
macro_rules! connect_async_full {
    ($object:expr, $async_method:ident, $relm:expr, $msg:expr) => {
        connect_async_full!($object, $async_method(), $relm, $msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:expr) => {{
        let cancellable = ::gio::Cancellable::new();
        let stream = ::relm::vendor::fragile::Fragile::new($relm.stream().clone());
        $object.$async_method($($args,)* Some(&cancellable), move |result| {
            if let Ok(result) = result {
                stream.into_inner().emit($msg(result));
            }
        });
        cancellable
    }};
    ($object:expr, $async_method:ident, $relm:expr, $msg:expr, $fail_msg:expr) => {
        connect_async_full!($object, $async_method(), $relm, $msg, $fail_msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:expr, $fail_msg:expr) => {{
        let cancellable = ::gio::Cancellable::new();
        let event_stream = ::relm::vendor::fragile::Fragile::new($relm.stream().clone());
        let fail_event_stream = ::relm::vendor::fragile::Fragile::new($relm.stream().clone());
        $object.$async_method($($args,)* Some(&cancellable), move |result| {
            match result {
                Ok(value) => event_stream.into_inner().emit($msg(value)),
                Err(error) => fail_event_stream.into_inner().emit($fail_msg(error)),
            }
        });

        cancellable
    }};
}

/// Like `connect_async_func!`, but also return a `Cancellable` to control the asynchronous request.
#[macro_export]
macro_rules! connect_async_func_full {
    ($class:ident :: $async_function:ident, $relm:expr, $msg:expr) => {
        connect_async!($async_func(), $relm, $msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:expr) => {{
        let cancellable = ::gio::Cancellable::new();
        let stream = ::relm::vendor::fragile::Fragile::new($relm.stream().clone());
        $class::$async_func($($args,)* Some(&cancellable), move |result| {
            if let Ok(result) = result {
                stream.into_inner().emit($msg(result));
            }
        });
        cancellable
    }};
    ($class:ident :: $async_func:ident, $relm:expr, $msg:expr, $fail_msg:expr) => {
        connect_async!($async_func(), $relm, $msg, $fail_msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:expr, $fail_msg:expr) => {{
        let cancellable = ::gio::Cancellable::new();
        let event_stream = ::relm::vendor::fragile::Fragile::new($relm.stream().clone());
        let fail_event_stream = ::relm::vendor::fragile::Fragile::new($relm.stream().clone());
        $class::$async_func($($args,)* Some(&cancellable), move |result| {
            match result {
                Ok(value) => event_stream.into_inner().emit($msg(value)),
                Err(error) => fail_event_stream.into_inner().emit($fail_msg(error)),
            }
        });

        cancellable
    }};
}
<commit_msg>Revert "Temporary fix to publish the crate"<commit_after>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

include!("../relm-state/src/macros.rs");
<|endoftext|>


<commit_before>fn main() {
	println!("Hello world!");
}
<commit_msg>primes<commit_after>fn main() {
	for i in 2..100 {
		let mut is_prime = true;
		for j in 2..(i/2)+1 {
			if i % j == 0 {
				is_prime = false;
				break;
			}
		}
		if is_prime {
			println!("{} is prime.", i);
		}
	}
}
<|endoftext|>


<commit_before>#[derive(Deserialize, Debug)]
pub struct AuthResponse {
    pub session: SessionResponse
}

#[derive(Deserialize, Debug, Clone)]
pub struct SessionResponse {
    pub key: String,
    pub subscriber: i64,
    pub name: String
}

#[derive(Deserialize, Debug)]
pub struct NowPlayingResponseWrapper {
    pub nowplaying: NowPlayingResponse
}

#[derive(Deserialize, Debug)]
pub struct NowPlayingResponse {
    pub artist: CorrectableString,
    pub album: CorrectableString,
    #[serde(rename="albumArtist")]
    pub album_artist: CorrectableString,
    pub track: CorrectableString
}

#[derive(Deserialize, Debug)]
pub struct CorrectableString {
    pub corrected: String,
    #[serde(rename="#text")]
    pub text: String
}
<commit_msg>Use a custom deserializer to deserialize 'corrected' field of now playing response fields to bool<commit_after>use serde;
use serde_json as json;

#[derive(Deserialize, Debug)]
pub struct AuthResponse {
    pub session: SessionResponse
}

#[derive(Deserialize, Debug, Clone)]
pub struct SessionResponse {
    pub key: String,
    pub subscriber: i64,
    pub name: String
}

#[derive(Deserialize, Debug)]
pub struct NowPlayingResponseWrapper {
    pub nowplaying: NowPlayingResponse
}

#[derive(Deserialize, Debug)]
pub struct NowPlayingResponse {
    pub artist: CorrectableString,
    pub album: CorrectableString,
    #[serde(rename="albumArtist")]
    pub album_artist: CorrectableString,
    pub track: CorrectableString
}

#[derive(Deserialize, Debug)]
pub struct CorrectableString {
    #[serde(deserialize_with="CorrectableString::deserialize_corrected_field")]
    pub corrected: bool,
    #[serde(rename="#text")]
    pub text: String
}

impl CorrectableString {

    fn deserialize_corrected_field<D>(de: D) -> Result<bool, D::Error>
        where D: serde::Deserializer
    {
        let deser_result: json::Value = try!(serde::Deserialize::deserialize(de));
        match deser_result {
            json::Value::String(ref s) if &*s == "1" => Ok(true),
            json::Value::String(ref s) if &*s == "0" => Ok(false),
            _ => Err(serde::de::Error::custom("Unexpected value")),
        }
    }

}<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;

use super::types;
use super::types::{MalValue, MalResult, new_list};
use super::types::MalType::{Symbol, List, Vector};

struct EnvData {
    data: HashMap<String, MalValue>,
    outer: Option<Env>,
}

/// Handler for an 'EnvData' instance.
pub type Env = Rc<RefCell<EnvData>>;

/// Create a new 'Env' instance with the (optional) outer environment.
pub fn new(outer: Option<Env>) -> Env {
    Rc::new(RefCell::new(EnvData { data: HashMap::new(), outer: outer}))
}

/// Return the root environment of the given 'Env'.
pub fn root(env: &Env) -> Env {
    match env.borrow().outer {
        Some(ref outer) => root(outer),
        None            => env.clone(),
    }
}

/// Return the given environment if it contains the given key (must be a Symbol)
/// or, if any, the first outer environment containing it.
pub fn find(env: &Env, key: &MalValue) -> Option<Env> {
    match **key {
        Symbol(ref symbol) => {
            let env_data = env.borrow();
            if env_data.data.contains_key(symbol) { Some(env.clone()) }
            else {
                match env_data.outer {
                    Some(ref outer_env) => find(outer_env, key),
                    None                => None,
                }
            }
        }
        _ => None,
    }
}

/// Associate the given key (must be a Symbol) with the given MAL value in the
/// given environment.
pub fn set(env: &Env, key: MalValue, val: MalValue) {
    match *key {
        Symbol(ref symbol) => { env.borrow_mut().data.insert(symbol.clone(), val); },
        _                  => warn!("env : cannot set with a non-symbol key"),
    }
}

/// Try to found, if it exists, the value with the associated key (must be a
/// Symbol) in the given environment and, if necessary, in its outer(s).
pub fn get(env: &Env, key: &MalValue) -> MalResult {
    match **key {
        Symbol(ref symbol) => match find(env, key) {
            Some(env) => Ok(env.borrow().data.get(symbol).unwrap().clone()),
            None      => types::err_string(format!("cannot find {}", symbol)),
        },
        _                  => types::err_str("env : cannot get with a non-symbol key"),
    }
}

/// Bind the given lists on a key/value basis and return the new environment,
/// with the given environment as its outer.
/// The binding will be variadic if a '&' symbol is encountered in the bindings
/// list ; in this case the next symbol in the bindings list is bound to the
//  rest of the exprs.
pub fn bind(outer: &Env, binds: MalValue, exprs: MalValue) -> Result<Env, String> {
    let env = new(Some(outer.clone()));
    let mut variadic_pos: Option<usize> = None;
    match *binds {
        List(ref binds_seq) | Vector(ref binds_seq) => {
            match *exprs {
                List(ref exprs_seq) | Vector(ref exprs_seq) => {
                    for (i, bind) in binds_seq.iter().enumerate() {
                        match **bind {
                            Symbol(ref bind_key) => {
                                if *bind_key == "&" {
                                    variadic_pos = Some(i);
                                    break;
                                } else if i >= exprs_seq.len() {
                                    return Err("not enough parameters for binding".into());
                                }
                                set(&env, bind.clone(), exprs_seq[i].clone());
                            },
                            _ => return Err("non-symbol bind".into()),
                        }
                    }
                    match variadic_pos {
                        Some(i) => {
                            if i >= binds_seq.len() {
                                return Err(concat!("missing a symbol after '&'",
                                           " for variadic binding").into());
                            }
                            let ref vbind = binds_seq[i+1];
                            match **vbind {
                                Symbol(_) => {
                                    set(&env, vbind.clone(),
                                        new_list(exprs_seq[i..].to_vec()));
                                },
                                _ => return Err("non'symbol variadic binding".into()),
                            }
                        },
                        None => (),
                    }
                    Ok(env)
                },
                _ => Err("env : exprs must be a list/vector".into()),
            }
        },
        _ => Err("env : binds must be a list/vector".into()),
    }
}
<commit_msg>Fixed compilation errors<commit_after>use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;

use super::types;
use super::types::{MalValue, MalResult, new_list};
use super::types::MalType::{Symbol, List, Vector};

pub struct EnvData {
    data: HashMap<String, MalValue>,
    outer: Option<Env>,
}

/// Handler for an 'EnvData' instance.
pub type Env = Rc<RefCell<EnvData>>;

/// Create a new 'Env' instance with the (optional) outer environment.
pub fn new(outer: Option<Env>) -> Env {
    Rc::new(RefCell::new(EnvData { data: HashMap::new(), outer: outer}))
}

/// Return the root environment of the given 'Env'.
pub fn root(env: &Env) -> Env {
    match env.borrow().outer {
        Some(ref outer) => root(outer),
        None            => env.clone(),
    }
}

/// Return the given environment if it contains the given key (must be a Symbol)
/// or, if any, the first outer environment containing it.
pub fn find(env: &Env, key: &MalValue) -> Option<Env> {
    match **key {
        Symbol(ref symbol) => {
            let env_data = env.borrow();
            if env_data.data.contains_key(symbol) { Some(env.clone()) }
            else {
                match env_data.outer {
                    Some(ref outer_env) => find(outer_env, key),
                    None                => None,
                }
            }
        }
        _ => None,
    }
}

/// Associate the given key (must be a Symbol) with the given MAL value in the
/// given environment.
pub fn set(env: &Env, key: MalValue, val: MalValue) {
    match *key {
        Symbol(ref symbol) => { env.borrow_mut().data.insert(symbol.clone(), val); },
        _                  => warn!("env : cannot set with a non-symbol key"),
    }
}

/// Try to found, if it exists, the value with the associated key (must be a
/// Symbol) in the given environment and, if necessary, in its outer(s).
pub fn get(env: &Env, key: &MalValue) -> MalResult {
    match **key {
        Symbol(ref symbol) => match find(env, key) {
            Some(env) => Ok(env.borrow().data.get(symbol).unwrap().clone()),
            None      => types::err_string(format!("cannot find {}", symbol)),
        },
        _                  => types::err_str("env : cannot get with a non-symbol key"),
    }
}

/// Bind the given lists on a key/value basis and return the new environment,
/// with the given environment as its outer.
/// The binding will be variadic if a '&' symbol is encountered in the bindings
/// list ; in this case the next symbol in the bindings list is bound to the
//  rest of the exprs.
pub fn bind(outer: &Env, binds: MalValue, exprs: MalValue) -> Result<Env, String> {
    let env = new(Some(outer.clone()));
    let mut variadic_pos: Option<usize> = None;
    match *binds {
        List(ref binds_seq) | Vector(ref binds_seq) => {
            match *exprs {
                List(ref exprs_seq) | Vector(ref exprs_seq) => {
                    for (i, bind) in binds_seq.iter().enumerate() {
                        match **bind {
                            Symbol(ref bind_key) => {
                                if *bind_key == "&" {
                                    variadic_pos = Some(i);
                                    break;
                                } else if i >= exprs_seq.len() {
                                    return Err("not enough parameters for binding".into());
                                }
                                set(&env, bind.clone(), exprs_seq[i].clone());
                            },
                            _ => return Err("non-symbol bind".into()),
                        }
                    }
                    match variadic_pos {
                        Some(i) => {
                            if i >= binds_seq.len() {
                                return Err(concat!("missing a symbol after '&'",
                                           " for variadic binding").into());
                            }
                            let ref vbind = binds_seq[i+1];
                            match **vbind {
                                Symbol(_) => {
                                    set(&env, vbind.clone(),
                                        new_list(exprs_seq[i..].to_vec()));
                                },
                                _ => return Err("non'symbol variadic binding".into()),
                            }
                        },
                        None => (),
                    }
                    Ok(env)
                },
                _ => Err("env : exprs must be a list/vector".into()),
            }
        },
        _ => Err("env : binds must be a list/vector".into()),
    }
}
<|endoftext|>


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

use libc::c_int;
use types::{
    Symmetry,
};

#[cfg(feature = "default")]
pub use rblas::matrix::{Matrix, BandMatrix};

#[cfg(not(feature = "default"))]
pub trait Matrix<T> {
    fn rows(&self) -> c_int;
    fn cols(&self) -> c_int;
    fn as_ptr(&self) -> *const T;
    fn as_mut_ptr(&mut self) -> *mut T;
}

#[cfg(not(feature = "default"))]
pub trait BandMatrix<T>: Matrix<T> {
    fn sub_diagonals(&self) -> c_int;
    fn sup_diagonals(&self) -> c_int;
}

pub trait TridiagonalMatrix<T>: Matrix<T> {
    fn as_ptrs(&self) -> (*const T, *const T, *const T);
    fn as_mut_ptrs(&self) -> (*mut T, *mut T, *mut T);
}

pub trait SymmetricMatrix<T>: Matrix<T> {
    fn symmetry(&self) -> Symmetry;
}

#[cfg(test)]
pub mod tests {
    use libc::c_int;
    use matrix::Matrix;

    pub struct M<T>(pub c_int, pub c_int, pub Vec<T>);

    impl<T> Matrix<T> for M<T> {
        fn rows(&self) -> c_int {
            self.0
        }

        fn cols(&self) -> c_int {
            self.1
        }

        fn as_ptr(&self) -> *const T {
            self.2[..].as_ptr()
        }

        fn as_mut_ptr(&mut self) -> *mut T {
            (&mut self.2[..]).as_mut_ptr()
        }
    }
}
<commit_msg>Remove import warning<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

#[cfg(not(feature = "default"))]
use libc::c_int;
use types::{
    Symmetry,
};

#[cfg(feature = "default")]
pub use rblas::matrix::{Matrix, BandMatrix};

#[cfg(not(feature = "default"))]
pub trait Matrix<T> {
    fn rows(&self) -> c_int;
    fn cols(&self) -> c_int;
    fn as_ptr(&self) -> *const T;
    fn as_mut_ptr(&mut self) -> *mut T;
}

#[cfg(not(feature = "default"))]
pub trait BandMatrix<T>: Matrix<T> {
    fn sub_diagonals(&self) -> c_int;
    fn sup_diagonals(&self) -> c_int;
}

pub trait TridiagonalMatrix<T>: Matrix<T> {
    fn as_ptrs(&self) -> (*const T, *const T, *const T);
    fn as_mut_ptrs(&self) -> (*mut T, *mut T, *mut T);
}

pub trait SymmetricMatrix<T>: Matrix<T> {
    fn symmetry(&self) -> Symmetry;
}

#[cfg(test)]
pub mod tests {
    use libc::c_int;
    use matrix::Matrix;

    pub struct M<T>(pub c_int, pub c_int, pub Vec<T>);

    impl<T> Matrix<T> for M<T> {
        fn rows(&self) -> c_int {
            self.0
        }

        fn cols(&self) -> c_int {
            self.1
        }

        fn as_ptr(&self) -> *const T {
            self.2[..].as_ptr()
        }

        fn as_mut_ptr(&mut self) -> *mut T {
            (&mut self.2[..]).as_mut_ptr()
        }
    }
}
<|endoftext|>