<commit_before>#![feature(non_ascii_idents)]

extern crate num;

extern crate special_fun;
extern crate roots;

use special_fun::FloatSpecial;
use std::f64::consts::PI;
use roots::SimpleConvergency;
use roots::find_root_brent;

fn jinc(r: f64) -> f64 {
    let π2r = 2.0f64*PI*r;
    2.0f64*π2r.besselj(1.0) / π2r
}

fn find_roots(a: f64, b: f64, f: &Fn(f64)->f64) -> Vec<f64> {
    let mut roots = Vec::new();
    const RANGES : i32 = 100;
    let dx = (b - a) / RANGES as f64;
    let conv = SimpleConvergency{eps:1e-12f64, max_iter:80};
    for r in 0..RANGES {
        let beg = a + (r as f64)*dx;
        let maybe_root = find_root_brent(beg, beg+dx, &f, &conv).ok();
        //match maybe_root {
        //    Some(root) => roots.push(root),
        //    None => {}
        //}
        if maybe_root.is_some() {
            roots.push(maybe_root.unwrap());
        }
    }

    roots
}

fn main() {
    let v = 0.5f64.besselj(1.0);
    println!("besselj(1.0, 0.5) : {}", v);
    println!("jinc(0.61) : {}", jinc(0.609835));

    let jinc_roots = find_roots(0f64, 5f64, &jinc);
    println!("jinc roots : {:?}", jinc_roots);
}
<commit_msg>use case for integrate crate.<commit_after>#![feature(non_ascii_idents)]

extern crate num;

extern crate special_fun;
extern crate roots;
extern crate integration;

use special_fun::FloatSpecial;
use std::f64::consts::PI;
use roots::SimpleConvergency;
use roots::find_root_brent;
use integration::quadrature;

fn jinc(r: f64) -> f64 {
    let π2r = 2.0f64*PI*r;
    2.0f64*π2r.besselj(1.0) / π2r
}

fn find_roots(a: f64, b: f64, f: &Fn(f64)->f64) -> Vec<f64> {
    let mut roots = Vec::new();
    const RANGES : i32 = 100;
    let dx = (b - a) / RANGES as f64;
    let conv = SimpleConvergency{eps:1e-12f64, max_iter:80};
    for r in 0..RANGES {
        let beg = a + (r as f64)*dx;
        let maybe_root = find_root_brent(beg, beg+dx, &f, &conv).ok();
        //match maybe_root {
        //    Some(root) => roots.push(root),
        //    None => {}
        //}
        if maybe_root.is_some() {
            roots.push(maybe_root.unwrap());
        }
    }

    roots
}

fn f(x: f64) -> f64 {
    quadrature::gauss_legendre(&|z: f64| z.besselj(1.0), 0.0, x, 1e-12)
}

fn main() {
    let v = 0.5f64.besselj(1.0);
    println!("besselj(1.0, 0.5) : {}", v);
    println!("jinc(0.61) : {}", jinc(0.609835));

    let jinc_roots = find_roots(0f64, 5f64, &jinc);
    println!("jinc roots : {:?}", jinc_roots);
    println!("f({}) = {}", 1000., f(1000.));
    println!("f({}) = {}", 3000., f(3000.));
}
<|endoftext|>


<commit_before>//! Key constants

/// Input key pressed and modifiers
pub type KeyEvent = (KeyCode, Modifiers);

/// Input key pressed
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum KeyCode {
    /// Unsupported escape sequence (on unix platform)
    UnknownEscSeq,
    /// ⌫ or Ctrl-H
    Backspace,
    /// ⇤ (usually Shift-Tab)
    BackTab,
    /// Paste (on unix platform)
    BracketedPasteStart,
    /// Paste (on unix platform)
    BracketedPasteEnd,
    /// Single char
    Char(char),
    /// ⌦
    Delete,
    /// ↓ arrow key
    Down,
    /// ⇲
    End,
    /// ↵ or Ctrl-M
    Enter,
    /// Escape or Ctrl-[
    Esc,
    /// Function key
    F(u8),
    /// ⇱
    Home,
    /// Insert key
    Insert,
    /// ← arrow key
    Left,
    /// \0
    Null,
    /// ⇟
    PageDown,
    /// ⇞
    PageUp,
    /// → arrow key
    Right,
    /// ⇥ or Ctrl-I
    Tab,
    /// ↑ arrow key
    Up,
}

bitflags::bitflags! {
    /// The set of modifier keys that were triggered along with a key press.
    pub struct Modifiers: u8 {
        /// Control modifier
        const CTRL  = 1<<3;
        /// Escape or Alt modifier
        const ALT  = 1<<2;
        /// Shift modifier
        const SHIFT = 1<<1;

        /// No modifier
        const NONE = 0;
        /// Ctrl + Shift
        const CTRL_SHIFT = Self::CTRL.bits | Self::SHIFT.bits;
        /// Alt + Shift
        const ALT_SHIFT = Self::ALT.bits | Self::SHIFT.bits;
        /// Ctrl + Alt
        const CTRL_ALT = Self::CTRL.bits | Self::ALT.bits;
        /// Ctrl + Alt + Shift
        const CTRL_ALT_SHIFT = Self::CTRL.bits | Self::ALT.bits | Self::SHIFT.bits;
    }
}

#[cfg(any(windows, unix))]
pub fn char_to_key_press(c: char, mut mods: Modifiers) -> KeyEvent {
    if !c.is_control() {
        if !mods.is_empty() {
            if c.is_ascii_uppercase() { // no SHIFT even if `c` is uppercase
                mods.remove(Modifiers::SHIFT);
            // } else if c.is_ascii_lowercase() && mods.contains(Modifiers::SHIFT) { TODO possible ?
            }
        }
        return (KeyCode::Char(c), mods);
    }
    #[allow(clippy::match_same_arms)]
    match c {
        '\x00' => (KeyCode::Char(' '), mods | Modifiers::CTRL),
        '\x01' => (KeyCode::Char('A'), mods | Modifiers::CTRL),
        '\x02' => (KeyCode::Char('B'), mods | Modifiers::CTRL),
        '\x03' => (KeyCode::Char('C'), mods | Modifiers::CTRL),
        '\x04' => (KeyCode::Char('D'), mods | Modifiers::CTRL),
        '\x05' => (KeyCode::Char('E'), mods | Modifiers::CTRL),
        '\x06' => (KeyCode::Char('F'), mods | Modifiers::CTRL),
        '\x07' => (KeyCode::Char('G'), mods | Modifiers::CTRL),
        '\x08' => (KeyCode::Backspace, mods), // '\b'
        '\x09' => { // '\t'
            if mods.contains(Modifiers::SHIFT) {
                mods.remove(Modifiers::SHIFT);
                (KeyCode::BackTab, mods)
            } else {
                (KeyCode::Tab, mods)
            }
        },
        '\x0a' => (KeyCode::Char('J'), mods | Modifiers::CTRL), // '\n' (10)
        '\x0b' => (KeyCode::Char('K'), mods | Modifiers::CTRL),
        '\x0c' => (KeyCode::Char('L'), mods | Modifiers::CTRL),
        '\x0d' => (KeyCode::Enter, mods), // '\r' (13)
        '\x0e' => (KeyCode::Char('N'), mods | Modifiers::CTRL),
        '\x0f' => (KeyCode::Char('O'), mods | Modifiers::CTRL),
        '\x10' => (KeyCode::Char('P'), mods | Modifiers::CTRL),
        '\x11' => (KeyCode::Char('Q'), mods | Modifiers::CTRL),
        '\x12' => (KeyCode::Char('R'), mods | Modifiers::CTRL),
        '\x13' => (KeyCode::Char('S'), mods | Modifiers::CTRL),
        '\x14' => (KeyCode::Char('T'), mods | Modifiers::CTRL),
        '\x15' => (KeyCode::Char('U'), mods | Modifiers::CTRL),
        '\x16' => (KeyCode::Char('V'), mods | Modifiers::CTRL),
        '\x17' => (KeyCode::Char('W'), mods | Modifiers::CTRL),
        '\x18' => (KeyCode::Char('X'), mods | Modifiers::CTRL),
        '\x19' => (KeyCode::Char('Y'), mods | Modifiers::CTRL),
        '\x1a' => (KeyCode::Char('Z'), mods | Modifiers::CTRL),
        '\x1b' => (KeyCode::Esc, mods), // Ctrl-[
        '\x1c' => (KeyCode::Char('\\'), mods | Modifiers::CTRL),
        '\x1d' => (KeyCode::Char(']'), mods | Modifiers::CTRL),
        '\x1e' => (KeyCode::Char('^'), mods | Modifiers::CTRL),
        '\x1f' => (KeyCode::Char('_'), mods | Modifiers::CTRL),
        '\x7f' => (KeyCode::Backspace, mods), // Rubout
        '\u{9b}' => (KeyCode::Esc, mods | Modifiers::SHIFT),
        _ => (KeyCode::Null, mods),
    }
}

#[cfg(test)]
mod tests {
    use super::{char_to_key_press, KeyCode, Modifiers};

    #[test]
    fn char_to_key() {
        assert_eq!((KeyCode::Esc, Modifiers::NONE), char_to_key_press('\x1b', Modifiers::NONE));
    }
}
<commit_msg>Remove SHIFT modifier for non control key<commit_after>//! Key constants

/// Input key pressed and modifiers
pub type KeyEvent = (KeyCode, Modifiers);

/// Input key pressed
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum KeyCode {
    /// Unsupported escape sequence (on unix platform)
    UnknownEscSeq,
    /// ⌫ or Ctrl-H
    Backspace,
    /// ⇤ (usually Shift-Tab)
    BackTab,
    /// Paste (on unix platform)
    BracketedPasteStart,
    /// Paste (on unix platform)
    BracketedPasteEnd,
    /// Single char
    Char(char),
    /// ⌦
    Delete,
    /// ↓ arrow key
    Down,
    /// ⇲
    End,
    /// ↵ or Ctrl-M
    Enter,
    /// Escape or Ctrl-[
    Esc,
    /// Function key
    F(u8),
    /// ⇱
    Home,
    /// Insert key
    Insert,
    /// ← arrow key
    Left,
    /// \0
    Null,
    /// ⇟
    PageDown,
    /// ⇞
    PageUp,
    /// → arrow key
    Right,
    /// ⇥ or Ctrl-I
    Tab,
    /// ↑ arrow key
    Up,
}

bitflags::bitflags! {
    /// The set of modifier keys that were triggered along with a key press.
    pub struct Modifiers: u8 {
        /// Control modifier
        const CTRL  = 1<<3;
        /// Escape or Alt modifier
        const ALT  = 1<<2;
        /// Shift modifier
        const SHIFT = 1<<1;

        /// No modifier
        const NONE = 0;
        /// Ctrl + Shift
        const CTRL_SHIFT = Self::CTRL.bits | Self::SHIFT.bits;
        /// Alt + Shift
        const ALT_SHIFT = Self::ALT.bits | Self::SHIFT.bits;
        /// Ctrl + Alt
        const CTRL_ALT = Self::CTRL.bits | Self::ALT.bits;
        /// Ctrl + Alt + Shift
        const CTRL_ALT_SHIFT = Self::CTRL.bits | Self::ALT.bits | Self::SHIFT.bits;
    }
}

#[cfg(any(windows, unix))]
pub fn char_to_key_press(c: char, mut mods: Modifiers) -> KeyEvent {
    if !c.is_control() {
        if !mods.is_empty() {
            mods.remove(Modifiers::SHIFT); // TODO Validate: no SHIFT even if `c` is uppercase
        }
        return (KeyCode::Char(c), mods);
    }
    #[allow(clippy::match_same_arms)]
    match c {
        '\x00' => (KeyCode::Char(' '), mods | Modifiers::CTRL),
        '\x01' => (KeyCode::Char('A'), mods | Modifiers::CTRL),
        '\x02' => (KeyCode::Char('B'), mods | Modifiers::CTRL),
        '\x03' => (KeyCode::Char('C'), mods | Modifiers::CTRL),
        '\x04' => (KeyCode::Char('D'), mods | Modifiers::CTRL),
        '\x05' => (KeyCode::Char('E'), mods | Modifiers::CTRL),
        '\x06' => (KeyCode::Char('F'), mods | Modifiers::CTRL),
        '\x07' => (KeyCode::Char('G'), mods | Modifiers::CTRL),
        '\x08' => (KeyCode::Backspace, mods), // '\b'
        '\x09' => { // '\t'
            if mods.contains(Modifiers::SHIFT) {
                mods.remove(Modifiers::SHIFT);
                (KeyCode::BackTab, mods)
            } else {
                (KeyCode::Tab, mods)
            }
        },
        '\x0a' => (KeyCode::Char('J'), mods | Modifiers::CTRL), // '\n' (10)
        '\x0b' => (KeyCode::Char('K'), mods | Modifiers::CTRL),
        '\x0c' => (KeyCode::Char('L'), mods | Modifiers::CTRL),
        '\x0d' => (KeyCode::Enter, mods), // '\r' (13)
        '\x0e' => (KeyCode::Char('N'), mods | Modifiers::CTRL),
        '\x0f' => (KeyCode::Char('O'), mods | Modifiers::CTRL),
        '\x10' => (KeyCode::Char('P'), mods | Modifiers::CTRL),
        '\x11' => (KeyCode::Char('Q'), mods | Modifiers::CTRL),
        '\x12' => (KeyCode::Char('R'), mods | Modifiers::CTRL),
        '\x13' => (KeyCode::Char('S'), mods | Modifiers::CTRL),
        '\x14' => (KeyCode::Char('T'), mods | Modifiers::CTRL),
        '\x15' => (KeyCode::Char('U'), mods | Modifiers::CTRL),
        '\x16' => (KeyCode::Char('V'), mods | Modifiers::CTRL),
        '\x17' => (KeyCode::Char('W'), mods | Modifiers::CTRL),
        '\x18' => (KeyCode::Char('X'), mods | Modifiers::CTRL),
        '\x19' => (KeyCode::Char('Y'), mods | Modifiers::CTRL),
        '\x1a' => (KeyCode::Char('Z'), mods | Modifiers::CTRL),
        '\x1b' => (KeyCode::Esc, mods), // Ctrl-[
        '\x1c' => (KeyCode::Char('\\'), mods | Modifiers::CTRL),
        '\x1d' => (KeyCode::Char(']'), mods | Modifiers::CTRL),
        '\x1e' => (KeyCode::Char('^'), mods | Modifiers::CTRL),
        '\x1f' => (KeyCode::Char('_'), mods | Modifiers::CTRL),
        '\x7f' => (KeyCode::Backspace, mods), // Rubout
        '\u{9b}' => (KeyCode::Esc, mods | Modifiers::SHIFT),
        _ => (KeyCode::Null, mods),
    }
}

#[cfg(test)]
mod tests {
    use super::{char_to_key_press, KeyCode, Modifiers};

    #[test]
    fn char_to_key() {
        assert_eq!((KeyCode::Esc, Modifiers::NONE), char_to_key_press('\x1b', Modifiers::NONE));
    }
}
<|endoftext|>


<commit_before>//! Write benchmark information to the output repository

use errors::{Result, ResultExt};

use std::fs::{self, read_dir, File, OpenOptions};
use std::io::{BufRead, BufReader, Read, Write};
use std::path::PathBuf;
use std::process::Command;
use std::str;
use std::collections::HashSet;

use serde_json;
use collector::CommitData;
use rust_sysroot::git::Commit as GitCommit;
use execute::Benchmark;

pub struct Repo {
    path: PathBuf,
    use_remote: bool,
    retries: Vec<String>,
}

impl Repo {
    fn git(&self, args: &[&str]) -> Result<()> {
        let mut command = Command::new("git");
        command.current_dir(&self.path);
        info!("git {:?}", args);
        command.args(args);
        let status = command
            .status()
            .chain_err(|| format!("could not spawn git {:?}", args))?;
        if !status.success() {
            bail!(
                "command `git {:?}` failed in `{}`",
                args,
                self.path.display()
            );
        }
        Ok(())
    }

    pub fn open(path: PathBuf, use_remote: bool) -> Result<Self> {
        let mut result = Repo {
            path: path,
            use_remote,
            retries: vec![],
        };

        if !result.retries_file().exists() {
            // try not to nuke random repositories.
            bail!("`{}` file not present", result.retries_file().display());
        }

        if result.use_remote {
            result.git(&["fetch"])?;
            result.git(&["reset", "--hard", "@{upstream}"])?;
        }

        fs::create_dir_all(result.times()).chain_err(|| "can't create `times/`")?;
        result.load_retries()?;

        Ok(result)
    }

    pub fn success(&self, data: &CommitData) -> Result<()> {
        self.add_commit_data(data)?;
        self.commit_and_push(&format!("{} - success", data.commit.sha))?;
        Ok(())
    }

    pub fn find_missing_commits<'a>(
        &self,
        commits: &'a [GitCommit],
        benchmarks: &[Benchmark],
        triple: &str,
    ) -> Result<Vec<&'a GitCommit>> {
        let mut have = HashSet::new();
        let path = self.times();
        for entry in read_dir(path)? {
            let entry = entry?;
            let filename = entry.file_name().to_string_lossy().to_string();
            let sha =
                &filename[filename.find("00:00").unwrap() + 6..filename.find("-x86").unwrap()];
            have.insert(sha.to_string());
        }

        let file = OpenOptions::new()
            .write(true)
            .read(true)
            .create(true)
            .open(self.broken_commits_file())?;
        let file = BufReader::new(file);
        for line in file.lines() {
            let line = line?;
            let sha = &line[..line.find(":").unwrap()];
            have.insert(sha.to_string());
        }

        let missing = commits
            .iter()
            .filter(|c| {
                !have.contains(&c.sha) || {
                    self.load_commit_data(c, triple)
                        .ok()
                        .map(|data| {
                            benchmarks
                                .iter()
                                .any(|b| data.benchmarks.keys().find(|k| **k == b.name).is_none())
                        })
                        .unwrap_or(true)
                }
            })
            .collect::<Vec<_>>();

        Ok(missing)
    }

    fn commit_and_push(&self, message: &str) -> Result<()> {
        self.write_retries()?;
        self.git(&["add", "retries", "times"])?;
        self.git(&["commit", "-m", message])?;
        if self.use_remote {
            self.git(&["push"])?;
        }
        Ok(())
    }

    pub fn load_commit_data(&self, commit: &GitCommit, triple: &str) -> Result<CommitData> {
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date.to_rfc3339(),
            commit.sha,
            triple
        ));
        info!("loading file {}", filepath.display());
        let mut file = File::open(&filepath)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        let data = serde_json::from_str(&contents)?;
        Ok(data)
    }

    pub fn add_commit_data(&self, data: &CommitData) -> Result<()> {
        let commit = &data.commit;
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date,
            commit.sha,
            data.triple
        ));
        info!("creating file {}", filepath.display());
        let mut file = File::create(&filepath)?;
        serde_json::to_writer(&mut file, &data)?;
        Ok(())
    }

    fn load_retries(&mut self) -> Result<()> {
        let mut retries = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(self.retries_file())
            .chain_err(|| {
                format!("can't create `{}`", self.retries_file().display())
            })?;
        let mut retries_s = String::new();
        retries.read_to_string(&mut retries_s)?;
        self.retries = retries_s
            .split('\n')
            .map(|line| line.trim())
            .filter(|line| !line.is_empty())
            .map(|line| if line.len() == 40 {
                Ok(line.to_owned())
            } else {
                bail!("bad retry hash `{}`", line)
            })
            .collect::<Result<_>>()?;
        info!("loaded retries: {:?}", self.retries);
        Ok(())
    }

    fn write_retries(&self) -> Result<()> {
        info!("writing retries");
        let mut retries = OpenOptions::new()
            .write(true)
            .truncate(true)
            .open(self.retries_file())
            .chain_err(|| "can't create `retries`")?;
        for retry in self.retries.iter() {
            writeln!(retries, "{}", retry)?;
        }
        Ok(())
    }

    pub fn next_retry(&mut self) -> Option<String> {
        if self.retries.len() == 0 {
            None
        } else {
            Some(self.retries.remove(0))
        }
    }

    fn broken_commits_file(&self) -> PathBuf {
        self.path.join("broken-commits-log")
    }

    fn retries_file(&self) -> PathBuf {
        self.path.join("retries")
    }

    pub fn times(&self) -> PathBuf {
        self.path.join("times")
    }
}
<commit_msg>Don't create broken-commits-file if it's not there<commit_after>//! Write benchmark information to the output repository

use errors::{Result, ResultExt};

use std::fs::{self, read_dir, File, OpenOptions};
use std::io::{BufRead, BufReader, Read, Write};
use std::path::PathBuf;
use std::process::Command;
use std::str;
use std::collections::HashSet;

use serde_json;
use collector::CommitData;
use rust_sysroot::git::Commit as GitCommit;
use execute::Benchmark;

pub struct Repo {
    path: PathBuf,
    use_remote: bool,
    retries: Vec<String>,
}

impl Repo {
    fn git(&self, args: &[&str]) -> Result<()> {
        let mut command = Command::new("git");
        command.current_dir(&self.path);
        info!("git {:?}", args);
        command.args(args);
        let status = command
            .status()
            .chain_err(|| format!("could not spawn git {:?}", args))?;
        if !status.success() {
            bail!(
                "command `git {:?}` failed in `{}`",
                args,
                self.path.display()
            );
        }
        Ok(())
    }

    pub fn open(path: PathBuf, use_remote: bool) -> Result<Self> {
        let mut result = Repo {
            path: path,
            use_remote,
            retries: vec![],
        };

        if !result.retries_file().exists() {
            // try not to nuke random repositories.
            bail!("`{}` file not present", result.retries_file().display());
        }

        if result.use_remote {
            result.git(&["fetch"])?;
            result.git(&["reset", "--hard", "@{upstream}"])?;
        }

        fs::create_dir_all(result.times()).chain_err(|| "can't create `times/`")?;
        result.load_retries()?;

        Ok(result)
    }

    pub fn success(&self, data: &CommitData) -> Result<()> {
        self.add_commit_data(data)?;
        self.commit_and_push(&format!("{} - success", data.commit.sha))?;
        Ok(())
    }

    pub fn find_missing_commits<'a>(
        &self,
        commits: &'a [GitCommit],
        benchmarks: &[Benchmark],
        triple: &str,
    ) -> Result<Vec<&'a GitCommit>> {
        let mut have = HashSet::new();
        let path = self.times();
        for entry in read_dir(path)? {
            let entry = entry?;
            let filename = entry.file_name().to_string_lossy().to_string();
            let sha =
                &filename[filename.find("00:00").unwrap() + 6..filename.find("-x86").unwrap()];
            have.insert(sha.to_string());
        }

        if let Ok(file) = File::open(self.broken_commits_file()) {
            let file = BufReader::new(file);
            for line in file.lines() {
                let line = line?;
                let sha = &line[..line.find(":").unwrap()];
                have.insert(sha.to_string());
            }
        }

        let missing = commits
            .iter()
            .filter(|c| {
                !have.contains(&c.sha) || {
                    self.load_commit_data(c, triple)
                        .ok()
                        .map(|data| {
                            benchmarks
                                .iter()
                                .any(|b| data.benchmarks.keys().find(|k| **k == b.name).is_none())
                        })
                        .unwrap_or(true)
                }
            })
            .collect::<Vec<_>>();

        Ok(missing)
    }

    fn commit_and_push(&self, message: &str) -> Result<()> {
        self.write_retries()?;
        self.git(&["add", "retries", "times"])?;
        self.git(&["commit", "-m", message])?;
        if self.use_remote {
            self.git(&["push"])?;
        }
        Ok(())
    }

    pub fn load_commit_data(&self, commit: &GitCommit, triple: &str) -> Result<CommitData> {
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date.to_rfc3339(),
            commit.sha,
            triple
        ));
        info!("loading file {}", filepath.display());
        let mut file = File::open(&filepath)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        let data = serde_json::from_str(&contents)?;
        Ok(data)
    }

    pub fn add_commit_data(&self, data: &CommitData) -> Result<()> {
        let commit = &data.commit;
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date,
            commit.sha,
            data.triple
        ));
        info!("creating file {}", filepath.display());
        let mut file = File::create(&filepath)?;
        serde_json::to_writer(&mut file, &data)?;
        Ok(())
    }

    fn load_retries(&mut self) -> Result<()> {
        let mut retries = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(self.retries_file())
            .chain_err(|| {
                format!("can't create `{}`", self.retries_file().display())
            })?;
        let mut retries_s = String::new();
        retries.read_to_string(&mut retries_s)?;
        self.retries = retries_s
            .split('\n')
            .map(|line| line.trim())
            .filter(|line| !line.is_empty())
            .map(|line| if line.len() == 40 {
                Ok(line.to_owned())
            } else {
                bail!("bad retry hash `{}`", line)
            })
            .collect::<Result<_>>()?;
        info!("loaded retries: {:?}", self.retries);
        Ok(())
    }

    fn write_retries(&self) -> Result<()> {
        info!("writing retries");
        let mut retries = OpenOptions::new()
            .write(true)
            .truncate(true)
            .open(self.retries_file())
            .chain_err(|| "can't create `retries`")?;
        for retry in self.retries.iter() {
            writeln!(retries, "{}", retry)?;
        }
        Ok(())
    }

    pub fn next_retry(&mut self) -> Option<String> {
        if self.retries.len() == 0 {
            None
        } else {
            Some(self.retries.remove(0))
        }
    }

    fn broken_commits_file(&self) -> PathBuf {
        self.path.join("broken-commits-log")
    }

    fn retries_file(&self) -> PathBuf {
        self.path.join("retries")
    }

    pub fn times(&self) -> PathBuf {
        self.path.join("times")
    }
}
<|endoftext|>


<commit_before>extern crate jsrs_parser;
extern crate jsrs_common;
extern crate rustyline;

mod value;
mod eval;

use std::env;
use std::io::prelude::*;
use std::io::{self, BufReader};
use std::path::Path;
use std::fs::{File, metadata};

use std::collections::HashMap;

use rustyline::error::ReadlineError;
use rustyline::Editor;

use eval::eval_string;

fn eval_file(filename: String, debug: bool) {
    let mut state = HashMap::new();

    println!("Reading from \"{}\"", filename);
    let path = Path::new(&filename);
    let file = File::open(&path)
        .expect(&format!("Cannot open \"{}\": no such file or directory", filename));
    let file_buffer = BufReader::new(file);

    for line in file_buffer.lines() {
        let mut input = String::from(line.unwrap().trim());

        if debug {
            println!(">> {:?}", input);
        }

        // insert semicolon if necessary
        if !input.ends_with(";") && !input.ends_with("}") {
            input.push_str(";");
        }

        if debug {
            println!("=> {:?}", eval_string(&input, &mut state));
            println!("** {:?}", state);
        }
    }
}

fn repl() {
    let mut state = HashMap::new();
    let mut rl = Editor::new();
    let mut stderr = io::stderr();

    if metadata(".history").is_ok() && rl.load_history(".history").is_err() {
        writeln!(stderr, "Error: unable to load history on startup").unwrap();
    }

    loop {
        // prompt
        let readline = rl.readline(">> ");

        match readline {
            Ok(line) => {
                rl.add_history_entry(&line);
                let mut input = String::from(line.trim());

                // ignore if only whitespace
                if input.len() == 0 {
                    continue;
                }

                // insert semicolon if necessary
                if !input.ends_with(";") && !input.ends_with("}") {
                    input.push_str(";");
                }

                rl.add_history_entry(&input);

                // eval
                println!("=> {:?}", eval_string(&input, &mut state));
                println!("** {:?}", state);
                println!("Line: {}", line);
            },
            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");

                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                }

                break
            },
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");

                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                }

                break
            },
            Err(err) => {
                println!("Error: {:?}", err);

                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                }

                break
            }
        }
    }
}

fn main() {
    let args = env::args();
    if args.len() > 1 {
        for file in args.skip(1) {
            eval_file(file, true);
        }
    } else {
        repl();
    }
}
<commit_msg>Remove extra output for ^D, ^C; add return value.<commit_after>extern crate jsrs_parser;
extern crate jsrs_common;
extern crate rustyline;

mod value;
mod eval;

use std::env;
use std::io::prelude::*;
use std::process::exit;
use std::io::{self, BufReader};
use std::path::Path;
use std::fs::{File, metadata};

use std::collections::HashMap;

use rustyline::error::ReadlineError;
use rustyline::Editor;

use eval::eval_string;

fn eval_file(filename: String, debug: bool) {
    let mut state = HashMap::new();

    println!("Reading from \"{}\"", filename);
    let path = Path::new(&filename);
    let file = File::open(&path)
        .expect(&format!("Cannot open \"{}\": no such file or directory", filename));
    let file_buffer = BufReader::new(file);

    for line in file_buffer.lines() {
        let mut input = String::from(line.unwrap().trim());

        if debug {
            println!(">> {:?}", input);
        }

        // insert semicolon if necessary
        if !input.ends_with(";") && !input.ends_with("}") {
            input.push_str(";");
        }

        if debug {
            println!("=> {:?}", eval_string(&input, &mut state));
            println!("** {:?}", state);
        }
    }
}

fn repl() -> i32 {
    let mut state = HashMap::new();
    let mut rl = Editor::new();
    let mut stderr = io::stderr();

    if metadata(".history").is_ok() && rl.load_history(".history").is_err() {
        writeln!(stderr, "Error: unable to load history on startup").unwrap();
    }

    loop {
        // prompt
        let readline = rl.readline(">> ");

        match readline {
            Ok(line) => {
                rl.add_history_entry(&line);
                let mut input = String::from(line.trim());

                // ignore if only whitespace
                if input.len() == 0 {
                    continue;
                }

                rl.add_history_entry(&input);

                // insert semicolon if necessary
                if !input.ends_with(";") && !input.ends_with("}") {
                    input.push_str(";");
                }

                // eval
                println!("=> {:?}", eval_string(&input, &mut state));
                println!("** {:?}", state);
                println!("Line: {}", line);
            },
            Err(ReadlineError::Interrupted) => {
                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                return 1;
            },
            Err(ReadlineError::Eof) => {
                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);

                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                return 3;
            }
        }
    }
    0
}

fn main() {
    let args = env::args();
    if args.len() > 1 {
        for file in args.skip(1) {
            eval_file(file, true);
        }
    } else {
        let ret = repl();
        exit(ret)
    }
}
<|endoftext|>


<commit_before>extern crate hyper;

use std::io;
use std::io::Write;
use std::fs::File;
use std::path::Path;

use std::net::{Ipv4Addr, SocketAddrV4};

use hyper::Server;
use hyper::server::Request;
use hyper::server::Response;
use hyper::header::ContentLength;
use hyper::net::Fresh;
use hyper::uri::RequestUri::AbsolutePath;

macro_rules! println_err {
    ($fmt: expr, $($arg:tt)*) => {
        match writeln!(&mut std::io::stderr(), $fmt,  $($arg)*) {
            Ok(_) => {},
            Err(_) => {}
        }
    };
}

macro_rules! try_return {
    ($e: expr) => {{
        match $e {
            Ok(v) => v,
            Err(e) => {
                println_err!("Error: {}", e);
                return;
            }
        }
    }}
}

fn handle_request(req: Request, mut resp: Response<Fresh>) {
    if let AbsolutePath(abs_path) = req.uri {
        if let Ok(file) = File::open(extract_path(&abs_path)) {
            try_return!(file_response(file, resp));
        } else {
            *resp.status_mut() = hyper::NotFound;
            try_return!(resp.send(b"
Not Found
"));
        }
    }
}

fn file_response(mut file: File, mut resp: Response<Fresh>) -> io::Result<u64> {
    let metadata = try!(file.metadata());
    resp.headers_mut().set(ContentLength(metadata.len()));
    resp.start().and_then(|mut res| io::copy(&mut file, &mut res))
}

fn extract_path(uri: &String) -> &Path {
    let first_question = uri.find('?').unwrap_or(uri.len());
    let slice = &uri[1 .. first_question];
    Path::new(slice)
}

fn main() {
    let ip = Ipv4Addr::new(127, 0, 0, 1);
    let port = std::env::args().nth(1).and_then(|p| p.parse::<u16>().ok()).unwrap_or(3000);

    let addr = SocketAddrV4::new(ip, port);

    match Server::http(addr) {
        Ok(server) => {
            println!("Server is listening at http://{}", addr);
            server.handle(handle_request).unwrap();
        },
        Err(error) => {
            println_err!("Unable to start server: {}", error);
            std::process::exit(1);
        }
    }
}
<commit_msg>Clean up error handling<commit_after>extern crate hyper;

use std::io;
use std::io::Write;
use std::fs::File;
use std::path::Path;

use std::net::{Ipv4Addr, SocketAddrV4};

use hyper::Server;
use hyper::server::Request;
use hyper::server::Response;
use hyper::header::ContentLength;
use hyper::net::Fresh;
use hyper::uri::RequestUri::AbsolutePath;
use hyper::status::StatusCode::NotFound;

macro_rules! println_err {
    ($fmt: expr, $($arg:tt)*) => {
        match writeln!(&mut std::io::stderr(), $fmt,  $($arg)*) {
            Ok(_) => {},
            Err(_) => {}
        }
    };
}

fn handle_request(req: Request, resp: Response<Fresh>) {
    let result = match req.uri {
        AbsolutePath(abs_path) => if let Ok(file) = File::open(extract_path(&abs_path)) {
            file_response(file, resp)
        } else {
            not_found(resp)
        },
        _ => not_found(resp)
    };
    match result {
        Err(e) => println_err!("Error: {}", e),
        _ => {}
    };
}

fn file_response(mut file: File, mut resp: Response<Fresh>) -> io::Result<()> {
    let metadata = try!(file.metadata());
    resp.headers_mut().set(ContentLength(metadata.len()));
    resp.start().and_then(|mut res| {
        try!(io::copy(&mut file, &mut res));
        res.end()
    })
}

fn not_found(mut resp: Response<Fresh>) -> io::Result<()> {
    *resp.status_mut() = NotFound;
    resp.send(b"
Not Found
")
}

fn extract_path(uri: &String) -> &Path {
    let first_question = uri.find('?').unwrap_or(uri.len());
    let slice = &uri[1 .. first_question];
    Path::new(slice)
}

fn main() {
    let ip = Ipv4Addr::new(127, 0, 0, 1);
    let port = std::env::args().nth(1).and_then(|p| p.parse::<u16>().ok()).unwrap_or(3000);

    let addr = SocketAddrV4::new(ip, port);

    match Server::http(addr) {
        Ok(server) => {
            println!("Server is listening at http://{}", addr);
            server.handle(handle_request).unwrap();
        },
        Err(error) => {
            println_err!("Unable to start server: {}", error);
            std::process::exit(1);
        }
    }
}
<|endoftext|>


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

extern crate gl;
extern crate glfw;

use std::{os,mem,ptr};
use std::path::Path;

use gl::types::*;
use glfw::Context;

use sceneio::read_scene;
use vec4::{Vec4,dot,transform_multiply};
use colour::Colour;
use scene::{Sphere,Material};

// module definition order matters for macro exports!
mod colour;
mod vec4;
mod mat4;
mod scene;
mod sceneio;

mod shaders;

static COLOUR_WIDTH:uint = 4;
static VERTEX_WIDTH:uint = 2;

fn make_gl_proj_mat(width: uint, height: uint) -> [GLfloat, ..16] {
  let mut m:[GLfloat, ..16] = [0.0, ..16];
  let w = width as f32;
  let h = height as f32;
  let f = 0.1;
  let n = 0.0;

  // from NDC to world space
  // translate by -1,-1 to put origin in bottom left
  // scale to change square 2,2 to rectangle w,h
  // flip Z because NDC is left handed

  // OpenGL matrix memory layout has transposition vector as the last row like D3D
  m[0] = 2.0 / w; // 2/(r-l)
  m[12] = -1.0;   // direct construction, so -1.0 rather than -(r+l)/(r-l)

  m[5] = 2.0 / h; // 2/(t-b)
  m[13] = -1.0;   // direct construction, so -1.0 rather than -(t+b)/(t-l)

  m[10] = -2.0 / (f - n);
  m[14] = -1.0 * (f + n) / (f - n);

  m[15] = 1.0;

  m
}

fn gl_init_and_render(scene: &scene::Scene) {
  let wx = scene.image_size.val0() as uint;
  let wy = scene.image_size.val1() as uint;

  let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

  // Choose a GL profile that is compatible with OS X 10.7+
  glfw.window_hint(glfw::ContextVersion(3, 2));
  glfw.window_hint(glfw::OpenglForwardCompat(true));
  glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));
  glfw.window_hint(glfw::Resizable(false));

  let (window, _) = glfw.create_window(wx as u32, wy as u32, "OpenGL", glfw::Windowed)
    .expect("Failed to create GLFW window.");

  // It is essential to make the context current before calling `gl::load_with`.
  window.make_current();

  // Load the OpenGL function pointers
  gl::load_with(|s| window.get_proc_address(s));

  // Create GLSL shaders
  let vs = shaders::compile_shader(shaders::VS_SRC, gl::VERTEX_SHADER);
  let fs = shaders::compile_shader(shaders::FS_SRC, gl::FRAGMENT_SHADER);
  let program = shaders::link_program(vs, fs);
  let mut vao = 0;

  // Add a vertex at every pixel... seems to cause issues at any res other than 800x600
  // TODO try building a texture instead
  let mut vbo = 0;
  let wy2 = wy * VERTEX_WIDTH;
  let vertex_data_vec: Vec<GLfloat> = Vec::from_fn(wx * wy2, |n| {
    let x = n / wy2;
    let y = n % wy2;
    let v = if y % 2 == 0 { x as f32 } else { (y / VERTEX_WIDTH) as f32};
    v + 0.5
  });
  let vertex_data = vertex_data_vec.as_slice();
  println!("{}", vertex_data[wx * wy2 - 4..]);

  // Add a colour for each vertex
  let mut cbo = 0;
  let wy4 = wy * COLOUR_WIDTH;
  let mut colour_data_vec: Vec<GLfloat> = Vec::from_fn(wx * wy4, |n| {
    match n % COLOUR_WIDTH {
      0 => (scene.background.red as f32   / 255.0) as GLfloat,
      1 => (scene.background.green as f32 / 255.0) as GLfloat,
      2 => (scene.background.blue as f32  / 255.0) as GLfloat,
      _ => 1.0
    }
  });
  let colour_data = colour_data_vec.as_mut_slice();

  unsafe {
    // Create Vertex Array Object
    gl::GenVertexArrays(1, &mut vao);
    gl::BindVertexArray(vao);

    // Set up vertex buffer object
    gl::GenBuffers(1, &mut vbo);
    gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
    gl::BufferData(gl::ARRAY_BUFFER,
                   (vertex_data.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
                   mem::transmute(&vertex_data[0]),
                   gl::STATIC_DRAW);

    // Set up colour buffer object
    gl::GenBuffers(1, &mut cbo);
    gl::BindBuffer(gl::ARRAY_BUFFER, cbo);
    gl::BufferData(gl::ARRAY_BUFFER,
                   (colour_data.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
                   mem::transmute(&colour_data[0]),
                   gl::STATIC_DRAW);

    gl::UseProgram(program);
    // Bind fragment shader
    "out_colour".with_c_str(|ptr| gl::BindFragDataLocation(program, 0, ptr));

    // Configure vertex buffer
    let pos_attr = "position".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
    gl::EnableVertexAttribArray(pos_attr as GLuint);
    gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
    gl::VertexAttribPointer(pos_attr as GLuint, VERTEX_WIDTH as i32, gl::FLOAT,
                            gl::FALSE as GLboolean, 0, ptr::null());

    // Set up the projection manually because we don't have glm or glu
    let proj = make_gl_proj_mat(wx, wy);
    let mvp_uni = "mvp".with_c_str(|ptr| gl::GetUniformLocation(program, ptr));

    // 3rd argument is transpose. GLES does not support this
    gl::UniformMatrix4fv(mvp_uni as GLint, 1, gl::FALSE as GLboolean,
                         mem::transmute(&proj[0]));

    // Configure colour buffer
    let col_attr = "vertex_colour".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
    gl::EnableVertexAttribArray(col_attr as GLuint);
    gl::BindBuffer(gl::ARRAY_BUFFER, cbo);
    gl::VertexAttribPointer(col_attr as GLuint, COLOUR_WIDTH as i32, gl::FLOAT,
                            gl::FALSE as GLboolean, 0, ptr::null());
  }

  let mut progress = 0;
  println!("starting loop");
  while progress < colour_data.len() {
    progress = render_step(scene, colour_data, progress);
  }
  println!("done");

  // TODO fix crap performance by using streaming, mapping the buffer, or using framebuffers etc
  // need to somehow decouple/desync changing the pixels and pushing to GPU
  while !window.should_close() {
    glfw.poll_events();
    unsafe {

      /*if progress < colour_data.len() {
        progress = render(scene, colour_data, progress);
      }*/

      gl::BufferData(gl::ARRAY_BUFFER,
                     (colour_data.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
                     mem::transmute(&colour_data[0]),
                     gl::STATIC_DRAW);

      gl::ClearColor(0.3, 0.3, 0.3, 1.0);
      gl::Clear(gl::COLOR_BUFFER_BIT);
      gl::DrawArrays(gl::POINTS, 0, vertex_data.len() as i32);
    }
    window.swap_buffers();
  }

  unsafe {
    gl::DeleteProgram(program);
    gl::DeleteShader(fs);
    gl::DeleteShader(vs);
    gl::DeleteBuffers(1, &cbo);
    gl::DeleteBuffers(1, &vbo);
    gl::DeleteVertexArrays(1, &vao);
  }
}

//fn trace(scene: &scene::Scene, ) -> Colour {
//
//}

type TestOpt = Option<(f64, f64)>;
type HitS<'a> = (&'a scene::Sphere, f64, f64);
type HitSOpt<'a> = Option<HitS<'a>>;

fn intersect_unit_sphere(u: &Vec4, v: &Vec4) -> TestOpt {
  // TODO perf these are the same for each object for a ray, so could manually cache them
  let uu = dot(u, u);
  let uv = dot(u, v);
  let vv = dot(v, v);

  let a = vv;
  let b = 2.0 * uv;
  let c = uu - 1.0;

  let ac4 = a * c * 4.0;
  let bsq =  b * b;

  if bsq <= ac4 {
    // < no real roots; miss
    // = 1  real root ; ray is tangent to sphere; treat as miss
    return None
  }

  let p = (bsq -  ac4).sqrt();

  let t1 = if b > 0.0 { (-b - p) / (2.0 * a) } else { (-b + p) / (2.0 * a) };
  let t2 = c / (a * t1);

  Some((t1, t2))
}

static mut debug: bool = false;
fn intersect_sphere<'a>(sphere: &'a scene::Sphere,  u: &Vec4, v: &Vec4) -> HitSOpt<'a> {
  let uprime = transform_multiply(&sphere.inverse_t, u);
  let vprime = transform_multiply(&sphere.inverse_t, v);

  unsafe { if debug {
    println!("s{} {}", u, v);
    println!("'{} {}", uprime, vprime);
  }}

  match intersect_unit_sphere(&uprime, &vprime) {
    Some(t) => Some((sphere, t.val0(), t.val1())),
    _ => None
  }
}

// TODO recursion depth
fn trace_ray(scene: &scene::Scene, u: &Vec4, v: &Vec4) -> Colour {
  // get sphere with max intersection less than (in front of) u.z
  // t will be negative if the hit is behind u

  // would be cleaner but less mathematically correct to return only nearest +ve t further down
  let hits: Vec<HitS> = scene.spheres.iter()
    .filter_map(|s| intersect_sphere(s, u, v))
    .filter(|h| h.val1() >= 0.0 || h.val2() >= 0.0)
    .collect::<Vec<HitS>>();

  let fake_s = sphere!();
  let fake_h = (&fake_s, std::f64::MAX_VALUE, std::f64::MAX_VALUE);
  let hit = hits.iter()
    .fold(fake_h, |s, h| { if h.val1().min(h.val2()) < s.val1().min(s.val2()) { *h } else { s }});

  if hit.val1() == fake_h.val1() && hit.val2() == fake_h.val2() {
    return scene.background;
    //return colour::BLACK;
  }

  return hit.val0().inner.diffuse;
}

// scene space => 1 ray per pixel(vertex), right handed system, but with 0,0 in the centre
// so need to translate by w/2 and h/2, don't flip Z because we should already be in an RH system
// and scale back to 2x2 plane
fn render_step(scene: &scene::Scene, colour_data: &mut [GLfloat], progress: uint) -> uint {
  let wx = scene.image_size.val0() as int;
  let wy = scene.image_size.val1() as int;

  let row = progress as int / (COLOUR_WIDTH as int * wy);
  let col = (progress as int % (COLOUR_WIDTH as int * wy)) / COLOUR_WIDTH as int;

  let hx = wx / 2;
  let hy = wy / 2;

  // Let our screen in object space be -1*wx/wy,-1,1 to 1*wx/wy,1,1
  // ray start
  let px = ((row - hx) as f64 + 0.5) / hy as f64;
  let py = ((col - hy) as f64 + 0.5) / hy as f64;
  let u = point!(px py 1.0);

  // ray direction
  // this is always the same, could cache it
  let dz = -1.0; // cleaner than using 0.0-1.0 to get macro to work
  let v = vector!(0.0 0.0 dz);

  /*let result = intersect_unit_sphere(&u, &v);

  if result != None {
    colour_data[progress] = 1.0;
    colour_data[progress + 2] = 0.0;
  }*/

  unsafe { debug = row == 400 && col == 300; }
  let colour = trace_ray(scene, &u, &v);
  colour_data[progress] = colour.red as f32 / 255.0;
  colour_data[progress + 1] = colour.green as f32 / 255.0;
  colour_data[progress + 2] = colour.blue as f32 / 255.0;

  progress + 4
}

fn load_scene_or_fail(filename: &Path) -> scene::Scene {
  let scene = match read_scene(filename) {
    Ok(scene) => {
      println!("\nParsed {}: {}", filename.display(), scene);
      scene
    },
    Err(desc) => {
      panic!("\nParsing {} failed\n\t {}", filename.display(), desc);
    }
  };

  for s in scene.spheres.iter() {
    mat4::matrix_print(&s.transform, "Transform");
    mat4::matrix_print(&s.inverse_t, "Inverse T");
  }

  scene
}

fn main() {
  let args = os::args();
  let print_usage = args.len() != 2u;

  if print_usage {
    println!("Usage:\n\t {} scene_file.txt", args[0]);
    return
  }

  let filename = Path::new(args[1].clone());
  let scene = load_scene_or_fail(&filename);

  gl_init_and_render(&scene);
}
<commit_msg>variable radius<commit_after>#![feature(slicing_syntax)]
#![feature(macro_rules)]
#![feature(phase)]
#![feature(globs)]

extern crate gl;
extern crate glfw;

use std::{os,mem,ptr};
use std::path::Path;

use gl::types::*;
use glfw::Context;

use sceneio::read_scene;
use vec4::{Vec4,dot,transform_multiply};
use colour::Colour;
use scene::{Sphere,Material};

// module definition order matters for macro exports!
mod colour;
mod vec4;
mod mat4;
mod scene;
mod sceneio;

mod shaders;

static COLOUR_WIDTH:uint = 4;
static VERTEX_WIDTH:uint = 2;

fn make_gl_proj_mat(width: uint, height: uint) -> [GLfloat, ..16] {
  let mut m:[GLfloat, ..16] = [0.0, ..16];
  let w = width as f32;
  let h = height as f32;
  let f = 0.1;
  let n = 0.0;

  // from NDC to world space
  // translate by -1,-1 to put origin in bottom left
  // scale to change square 2,2 to rectangle w,h
  // flip Z because NDC is left handed

  // OpenGL matrix memory layout has transposition vector as the last row like D3D
  m[0] = 2.0 / w; // 2/(r-l)
  m[12] = -1.0;   // direct construction, so -1.0 rather than -(r+l)/(r-l)

  m[5] = 2.0 / h; // 2/(t-b)
  m[13] = -1.0;   // direct construction, so -1.0 rather than -(t+b)/(t-l)

  m[10] = -2.0 / (f - n);
  m[14] = -1.0 * (f + n) / (f - n);

  m[15] = 1.0;

  m
}

fn gl_init_and_render(scene: &scene::Scene) {
  let wx = scene.image_size.val0() as uint;
  let wy = scene.image_size.val1() as uint;

  let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

  // Choose a GL profile that is compatible with OS X 10.7+
  glfw.window_hint(glfw::ContextVersion(3, 2));
  glfw.window_hint(glfw::OpenglForwardCompat(true));
  glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));
  glfw.window_hint(glfw::Resizable(false));

  let (window, _) = glfw.create_window(wx as u32, wy as u32, "OpenGL", glfw::Windowed)
    .expect("Failed to create GLFW window.");

  // It is essential to make the context current before calling `gl::load_with`.
  window.make_current();

  // Load the OpenGL function pointers
  gl::load_with(|s| window.get_proc_address(s));

  // Create GLSL shaders
  let vs = shaders::compile_shader(shaders::VS_SRC, gl::VERTEX_SHADER);
  let fs = shaders::compile_shader(shaders::FS_SRC, gl::FRAGMENT_SHADER);
  let program = shaders::link_program(vs, fs);
  let mut vao = 0;

  // Add a vertex at every pixel... seems to cause issues at any res other than 800x600
  // TODO try building a texture instead
  let mut vbo = 0;
  let wy2 = wy * VERTEX_WIDTH;
  let vertex_data_vec: Vec<GLfloat> = Vec::from_fn(wx * wy2, |n| {
    let x = n / wy2;
    let y = n % wy2;
    let v = if y % 2 == 0 { x as f32 } else { (y / VERTEX_WIDTH) as f32};
    v + 0.5
  });
  let vertex_data = vertex_data_vec.as_slice();
  println!("{}", vertex_data[wx * wy2 - 4..]);

  // Add a colour for each vertex
  let mut cbo = 0;
  let wy4 = wy * COLOUR_WIDTH;
  let mut colour_data_vec: Vec<GLfloat> = Vec::from_fn(wx * wy4, |n| {
    match n % COLOUR_WIDTH {
      0 => (scene.background.red as f32   / 255.0) as GLfloat,
      1 => (scene.background.green as f32 / 255.0) as GLfloat,
      2 => (scene.background.blue as f32  / 255.0) as GLfloat,
      _ => 1.0
    }
  });
  let colour_data = colour_data_vec.as_mut_slice();

  unsafe {
    // Create Vertex Array Object
    gl::GenVertexArrays(1, &mut vao);
    gl::BindVertexArray(vao);

    // Set up vertex buffer object
    gl::GenBuffers(1, &mut vbo);
    gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
    gl::BufferData(gl::ARRAY_BUFFER,
                   (vertex_data.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
                   mem::transmute(&vertex_data[0]),
                   gl::STATIC_DRAW);

    // Set up colour buffer object
    gl::GenBuffers(1, &mut cbo);
    gl::BindBuffer(gl::ARRAY_BUFFER, cbo);
    gl::BufferData(gl::ARRAY_BUFFER,
                   (colour_data.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
                   mem::transmute(&colour_data[0]),
                   gl::STATIC_DRAW);

    gl::UseProgram(program);
    // Bind fragment shader
    "out_colour".with_c_str(|ptr| gl::BindFragDataLocation(program, 0, ptr));

    // Configure vertex buffer
    let pos_attr = "position".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
    gl::EnableVertexAttribArray(pos_attr as GLuint);
    gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
    gl::VertexAttribPointer(pos_attr as GLuint, VERTEX_WIDTH as i32, gl::FLOAT,
                            gl::FALSE as GLboolean, 0, ptr::null());

    // Set up the projection manually because we don't have glm or glu
    let proj = make_gl_proj_mat(wx, wy);
    let mvp_uni = "mvp".with_c_str(|ptr| gl::GetUniformLocation(program, ptr));

    // 3rd argument is transpose. GLES does not support this
    gl::UniformMatrix4fv(mvp_uni as GLint, 1, gl::FALSE as GLboolean,
                         mem::transmute(&proj[0]));

    // Configure colour buffer
    let col_attr = "vertex_colour".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
    gl::EnableVertexAttribArray(col_attr as GLuint);
    gl::BindBuffer(gl::ARRAY_BUFFER, cbo);
    gl::VertexAttribPointer(col_attr as GLuint, COLOUR_WIDTH as i32, gl::FLOAT,
                            gl::FALSE as GLboolean, 0, ptr::null());
  }

  let mut progress = 0;
  println!("starting loop");
  while progress < colour_data.len() {
    progress = render_step(scene, colour_data, progress);
  }
  println!("done");

  // TODO fix crap performance by using streaming, mapping the buffer, or using framebuffers etc
  // need to somehow decouple/desync changing the pixels and pushing to GPU
  while !window.should_close() {
    glfw.poll_events();
    unsafe {

      /*if progress < colour_data.len() {
        progress = render(scene, colour_data, progress);
      }*/

      gl::BufferData(gl::ARRAY_BUFFER,
                     (colour_data.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
                     mem::transmute(&colour_data[0]),
                     gl::STATIC_DRAW);

      gl::ClearColor(0.3, 0.3, 0.3, 1.0);
      gl::Clear(gl::COLOR_BUFFER_BIT);
      gl::DrawArrays(gl::POINTS, 0, vertex_data.len() as i32);
    }
    window.swap_buffers();
  }

  unsafe {
    gl::DeleteProgram(program);
    gl::DeleteShader(fs);
    gl::DeleteShader(vs);
    gl::DeleteBuffers(1, &cbo);
    gl::DeleteBuffers(1, &vbo);
    gl::DeleteVertexArrays(1, &vao);
  }
}

//fn trace(scene: &scene::Scene, ) -> Colour {
//
//}

type TestOpt = Option<(f64, f64)>;
type HitS<'a> = (&'a scene::Sphere, f64, f64);
type HitSOpt<'a> = Option<HitS<'a>>;

fn intersect_fixed_sphere(u: &Vec4, v: &Vec4, r: f64) -> TestOpt {
  // TODO perf these are the same for each object for a ray, so could manually cache them
  let uu = dot(u, u);
  let uv = dot(u, v);
  let vv = dot(v, v);

  let a = vv;
  let b = 2.0 * uv;
  let c = uu - r * r;

  let ac4 = a * c * 4.0;
  let bsq =  b * b;

  if bsq <= ac4 {
    // < no real roots; miss
    // = 1  real root ; ray is tangent to sphere; treat as miss
    return None
  }

  let p = (bsq -  ac4).sqrt();

  let t1 = if b > 0.0 { (-b - p) / (2.0 * a) } else { (-b + p) / (2.0 * a) };
  let t2 = c / (a * t1);

  Some((t1, t2))
}

static mut debug: bool = false;
fn intersect_sphere<'a>(sphere: &'a scene::Sphere,  u: &Vec4, v: &Vec4) -> HitSOpt<'a> {
  let uprime = transform_multiply(&sphere.inverse_t, u);
  let vprime = transform_multiply(&sphere.inverse_t, v);

  unsafe { if debug {
    println!("s{} {}", u, v);
    println!("'{} {}", uprime, vprime);
  }}

  match intersect_fixed_sphere(&uprime, &vprime, sphere.radius) {
    Some(t) => Some((sphere, t.val0(), t.val1())),
    _ => None
  }
}

// TODO recursion depth
fn trace_ray(scene: &scene::Scene, u: &Vec4, v: &Vec4) -> Colour {
  // get sphere with max intersection less than (in front of) u.z
  // t will be negative if the hit is behind u

  // would be cleaner but less mathematically correct to return only nearest +ve t further down
  let hits: Vec<HitS> = scene.spheres.iter()
    .filter_map(|s| intersect_sphere(s, u, v))
    .filter(|h| h.val1() >= 0.0 || h.val2() >= 0.0)
    .collect::<Vec<HitS>>();

  let fake_s = sphere!();
  let fake_h = (&fake_s, std::f64::MAX_VALUE, std::f64::MAX_VALUE);
  let hit = hits.iter()
    .fold(fake_h, |s, h| { if h.val1().min(h.val2()) < s.val1().min(s.val2()) { *h } else { s }});

  if hit.val1() == fake_h.val1() && hit.val2() == fake_h.val2() {
    return scene.background;
    //return colour::BLACK;
  }

  return hit.val0().inner.diffuse;
}

// scene space => 1 ray per pixel(vertex), right handed system, but with 0,0 in the centre
// so need to translate by w/2 and h/2, don't flip Z because we should already be in an RH system
// and scale back to 2x2 plane
fn render_step(scene: &scene::Scene, colour_data: &mut [GLfloat], progress: uint) -> uint {
  let wx = scene.image_size.val0() as int;
  let wy = scene.image_size.val1() as int;

  let row = progress as int / (COLOUR_WIDTH as int * wy);
  let col = (progress as int % (COLOUR_WIDTH as int * wy)) / COLOUR_WIDTH as int;

  let hx = wx / 2;
  let hy = wy / 2;

  // Let our screen in object space be -1*wx/wy,-1,1 to 1*wx/wy,1,1
  // ray start
  let px = ((row - hx) as f64 + 0.5) / hy as f64;
  let py = ((col - hy) as f64 + 0.5) / hy as f64;
  let u = point!(px py 1.0);

  // ray direction
  // this is always the same, could cache it
  let dz = -1.0; // cleaner than using 0.0-1.0 to get macro to work
  let v = vector!(0.0 0.0 dz);

  /*let result = intersect_unit_sphere(&u, &v);

  if result != None {
    colour_data[progress] = 1.0;
    colour_data[progress + 2] = 0.0;
  }*/

  //unsafe { debug = row == hx && col == hy; }
  let colour = trace_ray(scene, &u, &v);
  // TODO cleaner way to do this
  // TODO freeze scene after IO
  colour_data[progress] = colour.red as f32 / 255.0;
  colour_data[progress + 1] = colour.green as f32 / 255.0;
  colour_data[progress + 2] = colour.blue as f32 / 255.0;

  progress + 4
}

fn load_scene_or_fail(filename: &Path) -> scene::Scene {
  let scene = match read_scene(filename) {
    Ok(scene) => {
      println!("\nParsed {}: {}", filename.display(), scene);
      scene
    },
    Err(desc) => {
      panic!("\nParsing {} failed\n\t {}", filename.display(), desc);
    }
  };

  for s in scene.spheres.iter() {
    mat4::matrix_print(&s.transform, "Transform");
    mat4::matrix_print(&s.inverse_t, "Inverse T");
  }

  scene
}

fn main() {
  let args = os::args();
  let print_usage = args.len() != 2u;

  if print_usage {
    println!("Usage:\n\t {} scene_file.txt", args[0]);
    return
  }

  let filename = Path::new(args[1].clone());
  let scene = load_scene_or_fail(&filename);

  gl_init_and_render(&scene);
}
<|endoftext|>


<commit_before>extern crate sdl;
extern crate rand;

use rand::distribuitions::{IndependentSample, Range};
use sdl::video::{SurfaceFlag, VideoFlag, Color};
use sdl::event::{Event, Key};

fn init(screen_width: isize, screen_height: isize) -> sdl::video::Surface {
    sdl::init(&[sdl::InitFlag::Video]);
    sdl::wm::set_caption("mines", "mines");

    let screen = match sdl::video::set_video_mode(screen_width, screen_height, 32,
                                                  &[SurfaceFlag::HWSurface],
                                                  &[VideoFlag::DoubleBuf]) {
        Ok(screen) => screen,
        Err(err) => panic!("failed to set video mode: {}", err)
    };
    screen
}

fn draw_square(x: i16, y: i16, w: u16, (r,g,b): (u8, u8, u8), screen: &sdl::video::Surface) {
    screen.fill_rect(Some(sdl::Rect {x: x, y: y, w: w, h: w}), Color::RGB(r, g, b));
}

fn draw_num(n: u8, x: i16, y: i16, size: u16, screen: &sdl::video::Surface) {
    let mut n = n;
    let sub = (size-1) as i16/3;
    let pack = (size as i16-sub*3)as i16/2;
    let color = if n == 1 {
        (100,100,255)
    }else if n == 2 {
        (0,255,0)
    }else if n == 3 {
        (255,0,0)
    }else if n == 4 {
        (0,0,255)
    }else if n == 5 {
        (200,50,0)
    }else if n == 6 {
        (0,255,255)
    }else if n == 7 {
        (0,0,0)
    }else {
        (150,150,150)
    };

    loop {
        if n == 0 {break;}
        else if n == 1{
            draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color, screen);
            break;
        }else if n == 2{
            draw_square(x+pack, y+pack, sub as u16-1,  color, screen);
            draw_square(sub*2+x+pack, sub*2+y+pack, sub as u16-1, color, screen);
            break;
        }else if n == 3{
            draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color, screen);
            n = 2;
        }else if n == 4{
            draw_square(x+pack, sub*2+y+pack, sub as u16-1, color, screen);
            draw_square(sub*2+x+pack, y+pack, sub as u16-1, color, screen);
            n = 2;
        }else if n == 5{
            draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color, screen);
            n = 4;
        }else if n == 6{
            draw_square(x+pack, sub+y+pack, sub as u16-1, color, screen);
            draw_square(sub*2+x+pack, sub+y+pack, sub as u16-1, color, screen);
            n = 4;
        }else if n == 7{
            draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color, screen);
            n = 6;
        }else if n == 8{
            draw_square(sub+x+pack, y+pack, sub as u16-1, color, screen);
            draw_square(sub+x+pack, sub*2+y+pack, sub as u16-1, color, screen);
            n = 6;
        }
    }
}

fn draw_field(ref field: &Vec<Vec<bool>>, length: i16, screen: &sdl::video::Surface) {
    let mut n = 0;
    for ref i in field.iter() {
        let mut m = 0;
        for ref j in i.iter() {
            draw_square(m*length+1,
                      n*length+1,
                      (length-1) as u16,
                      if **j {(0, 0, 0)} else {(255, 255, 255)},
                      screen
            );
            if !**j{
                draw_num(
                    count_field(m as usize, n as usize, field),
                    m as i16*length as i16+1,
                    n as i16*length as i16+1,
                    (length-1) as u16,
                    screen);
            }
            m += 1;
        }
        n += 1;
    }
}

fn flip_field(ref mut field: &mut Vec<Vec<bool>>, x: i16, y: i16, size: i16) {
    let i = (x/size) as usize;
    let j = (y/size) as usize;
    field[i][j] = !(field[i][j]);
}

fn random_field(r: f32, field: &mut Vec<Vec<bool>>) {
    let bt = Range::new(0.,1);
    let mut rng = rang::thread_rng();
    field.iter().map(|x| {x.map(|y| {
        if rn%1 > bt.ind_sample(&mut rng) {
            true
        }else{
            false
        }

    })});
    let rng = rand::thread_rng();
}

fn count_field(x: usize, y: usize, field: &Vec<Vec<bool>>) -> u8 {
    let w = field[0].len();
    let h = field.len();
    let mut n = 0;
    for i in 0..3 {
        if y+i == 0 || y+i == h+1 {continue;}
        for j in 0..3 {
            if i == 1 && j == 1 {continue;}
            if x+j == 0 || x+j == w+1 {continue;}
            if field[y+i-1][x+j-1] {n += 1}
        }
    }
    n
}

fn main() {
    const WIDTH: usize = 30;
    const HEIGHT: usize = 20;
    const SIZE: usize = 35;

    let field = &mut vec![vec![false; WIDTH]; HEIGHT];

    let screen = init((SIZE*WIDTH) as isize + 1, (SIZE*HEIGHT) as isize + 1);
    loop {
        match sdl::event::poll_event() {
            Event::Quit => break,
            Event::MouseButton(_, down, mx, my) => {
                if down {
                    flip_field(field, my as i16, mx as i16, SIZE as i16);
                    println!("{}", count_field((mx/SIZE as u16) as usize, (my/SIZE as u16) as usize, field));
                }
            },
            Event::Key(k, _, _, _)
                if k == Key::Escape
                    => break,
            _ => {}
        }
        draw_field(&field, SIZE as i16, &screen);
        screen.flip();
    }

    sdl::quit();
}
<commit_msg>silly typos<commit_after>extern crate sdl;
extern crate rand;

use rand::distributions::{IndependentSample, Range};
use sdl::video::{SurfaceFlag, VideoFlag, Color};
use sdl::event::{Event, Key};

fn init(screen_width: isize, screen_height: isize) -> sdl::video::Surface {
    sdl::init(&[sdl::InitFlag::Video]);
    sdl::wm::set_caption("mines", "mines");

    let screen = match sdl::video::set_video_mode(screen_width, screen_height, 32,
                                                  &[SurfaceFlag::HWSurface],
                                                  &[VideoFlag::DoubleBuf]) {
        Ok(screen) => screen,
        Err(err) => panic!("failed to set video mode: {}", err)
    };
    screen
}

fn draw_square(x: i16, y: i16, w: u16, (r,g,b): (u8, u8, u8), screen: &sdl::video::Surface) {
    screen.fill_rect(Some(sdl::Rect {x: x, y: y, w: w, h: w}), Color::RGB(r, g, b));
}

fn draw_num(n: u8, x: i16, y: i16, size: u16, screen: &sdl::video::Surface) {
    let mut n = n;
    let sub = (size-1) as i16/3;
    let pack = (size as i16-sub*3)as i16/2;
    let color = if n == 1 {
        (100,100,255)
    }else if n == 2 {
        (0,255,0)
    }else if n == 3 {
        (255,0,0)
    }else if n == 4 {
        (0,0,255)
    }else if n == 5 {
        (200,50,0)
    }else if n == 6 {
        (0,255,255)
    }else if n == 7 {
        (0,0,0)
    }else {
        (150,150,150)
    };

    loop {
        if n == 0 {break;}
        else if n == 1{
            draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color, screen);
            break;
        }else if n == 2{
            draw_square(x+pack, y+pack, sub as u16-1,  color, screen);
            draw_square(sub*2+x+pack, sub*2+y+pack, sub as u16-1, color, screen);
            break;
        }else if n == 3{
            draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color, screen);
            n = 2;
        }else if n == 4{
            draw_square(x+pack, sub*2+y+pack, sub as u16-1, color, screen);
            draw_square(sub*2+x+pack, y+pack, sub as u16-1, color, screen);
            n = 2;
        }else if n == 5{
            draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color, screen);
            n = 4;
        }else if n == 6{
            draw_square(x+pack, sub+y+pack, sub as u16-1, color, screen);
            draw_square(sub*2+x+pack, sub+y+pack, sub as u16-1, color, screen);
            n = 4;
        }else if n == 7{
            draw_square(sub+x+pack, sub+y+pack, sub as u16-1, color, screen);
            n = 6;
        }else if n == 8{
            draw_square(sub+x+pack, y+pack, sub as u16-1, color, screen);
            draw_square(sub+x+pack, sub*2+y+pack, sub as u16-1, color, screen);
            n = 6;
        }
    }
}

fn draw_field(ref field: &Vec<Vec<bool>>, length: i16, screen: &sdl::video::Surface) {
    let mut n = 0;
    for ref i in field.iter() {
        let mut m = 0;
        for ref j in i.iter() {
            draw_square(m*length+1,
                      n*length+1,
                      (length-1) as u16,
                      if **j {(0, 0, 0)} else {(255, 255, 255)},
                      screen
            );
            if !**j{
                draw_num(
                    count_field(m as usize, n as usize, field),
                    m as i16*length as i16+1,
                    n as i16*length as i16+1,
                    (length-1) as u16,
                    screen);
            }
            m += 1;
        }
        n += 1;
    }
}

fn flip_field(ref mut field: &mut Vec<Vec<bool>>, x: i16, y: i16, size: i16) {
    let i = (x/size) as usize;
    let j = (y/size) as usize;
    field[i][j] = !(field[i][j]);
}

fn random_field(r: f32, field: &mut Vec<Vec<bool>>) {
    let bt = Range::new(0.,1.);
    let mut rng = rand::thread_rng();
    field.iter().map(|x| {x.map(|y| {
        if bt.ind_sample(&mut rng) < r {
            true
        }else{
            false
        }

    })});
    let rng = rand::thread_rng();
}

fn count_field(x: usize, y: usize, field: &Vec<Vec<bool>>) -> u8 {
    let w = field[0].len();
    let h = field.len();
    let mut n = 0;
    for i in 0..3 {
        if y+i == 0 || y+i == h+1 {continue;}
        for j in 0..3 {
            if i == 1 && j == 1 {continue;}
            if x+j == 0 || x+j == w+1 {continue;}
            if field[y+i-1][x+j-1] {n += 1}
        }
    }
    n
}

fn main() {
    const WIDTH: usize = 30;
    const HEIGHT: usize = 20;
    const SIZE: usize = 35;

    let field = &mut vec![vec![false; WIDTH]; HEIGHT];

    let screen = init((SIZE*WIDTH) as isize + 1, (SIZE*HEIGHT) as isize + 1);
    loop {
        match sdl::event::poll_event() {
            Event::Quit => break,
            Event::MouseButton(_, down, mx, my) => {
                if down {
                    flip_field(field, my as i16, mx as i16, SIZE as i16);
                    println!("{}", count_field((mx/SIZE as u16) as usize, (my/SIZE as u16) as usize, field));
                }
            },
            Event::Key(k, _, _, _)
                if k == Key::Escape
                    => break,
            _ => {}
        }
        draw_field(&field, SIZE as i16, &screen);
        screen.flip();
    }

    sdl::quit();
}
<|endoftext|>


<commit_before>extern crate tray_rust;

use std::vec::Vec;
use std::sync::{Arc, TaskPool};
use std::io::timer;
use std::time::duration::Duration;
use tray_rust::linalg;
use tray_rust::film;
use tray_rust::geometry;
use tray_rust::geometry::Geometry;
use tray_rust::sampler;
use tray_rust::sampler::{Sampler};

/// Trial of how we might do the render target stuff.
/// Threads are each sent a send end of the channel that is
/// read from by the render target thread which then saves the
/// values recieved to the framebuffer
fn thread_work(tx: Sender<uint>, i: uint, queue: Arc<sampler::BlockQueue>) {
    for _ in queue.iter() {
        tx.send(i);
        // Pretend to do some work
        timer::sleep(Duration::milliseconds(50));
    }
}

/// Hand the workers their own send endpoints to communicate results back
/// to the main thread but drop the sender on the main thread so once
/// all threads finish the channel closes
fn spawn_workers(pool: &TaskPool, n: uint) -> Receiver<uint> {
    let (tx, rx) = channel();
    let block_queue = Arc::new(sampler::BlockQueue::new((10, 10), (2, 2)));
    for i in range(0, n) {
        let t = tx.clone();
        let q = block_queue.clone();
        // Can we just directly pass thread_work here? How would we send the args?
        pool.execute(move || {
            thread_work(t, i, q);
        });
    }
    rx
}

fn thread_test() {
    let n = 8;
    let pool = TaskPool::new(n);
    let rx = spawn_workers(&pool, n);
    for m in rx.iter() {
        println!("Message: {}", m);
    }
}

fn main() {
    thread_test();
    let width = 800u;
    let height = 600u;

    let mut rt = film::RenderTarget::new(width, height);
    let camera = film::Camera::new(linalg::Transform::look_at(
        &linalg::Point::new(0.0, 0.0, -10.0), &linalg::Point::new(0.0, 0.0, 0.0),
        &linalg::Vector::new(0.0, 1.0, 0.0)), 40.0, rt.dimensions());
    let sphere = geometry::Sphere::new(1.5);
    let instance = geometry::Instance::new(&sphere,
        linalg::Transform::translate(&linalg::Vector::new(0.0, 2.0, 0.0)));

    let block_queue = sampler::BlockQueue::new((width as u32, height as u32), (8, 8));
    let mut sampler = sampler::Uniform::new(block_queue.block_dim());
    let mut sample_pos = Vec::with_capacity(sampler.max_spp());
    for b in block_queue.iter() {
        sampler.select_block(&b);
        while sampler.has_samples() {
            sampler.get_samples(&mut sample_pos);
            for px in sample_pos.iter() {
                let mut ray = camera.generate_ray(*px);
                match instance.intersect(&mut ray) {
                    Some(_) => rt.write(px.0, px.1, &film::Colorf::broadcast(1.0)),
                    None => rt.write(px.0, px.1, &film::Colorf::new(0.0, 0.0, 1.0)),
                }
            }
        }
    }
    film::write_ppm("out.ppm", width, height, rt.get_render().as_slice());
}

<commit_msg>Initial crazy rough super bad trial of threading<commit_after>extern crate tray_rust;

use std::vec::Vec;
use std::sync::{Arc, TaskPool};
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};
use std::time::duration::Duration;

use tray_rust::linalg;
use tray_rust::film;
use tray_rust::geometry;
use tray_rust::geometry::Geometry;
use tray_rust::sampler;
use tray_rust::sampler::{Sampler};

static WIDTH: uint = 800;
static HEIGHT: uint = 600;

/// Trial of how we might do the render target stuff.
/// Threads are each sent a send end of the channel that is
/// read from by the render target thread which then saves the
/// values recieved to the framebuffer
fn thread_work(tx: Sender<(f32, f32, film::Colorf)>, queue: Arc<sampler::BlockQueue>) {
    // TODO: Sharing this between the threads? How?
    let camera = film::Camera::new(linalg::Transform::look_at(
        &linalg::Point::new(0.0, 0.0, -10.0), &linalg::Point::new(0.0, 0.0, 0.0),
        &linalg::Vector::new(0.0, 1.0, 0.0)), 40.0, (WIDTH, HEIGHT));
    let sphere = geometry::Sphere::new(1.5);
    let instance = Arc::new(geometry::Instance::new(&sphere,
        linalg::Transform::translate(&linalg::Vector::new(0.0, 2.0, 0.0))));
    let mut sampler = sampler::Uniform::new(queue.block_dim());
    let mut samples = Vec::with_capacity(sampler.max_spp());
    let mut sample_pos = Vec::with_capacity(sampler.max_spp());
    for b in queue.iter() {
        sampler.select_block(&b);
        while sampler.has_samples() {
            sampler.get_samples(&mut sample_pos);
            for px in sample_pos.iter() {
                let mut ray = camera.generate_ray(*px);
                match instance.intersect(&mut ray) {
                    Some(_) => samples.push((px.0, px.1, film::Colorf::broadcast(1.0))),
                    None => samples.push((px.0, px.1, film::Colorf::new(0.0, 0.0, 1.0))),
                }
            }
            for s in samples.iter() {
                match tx.send(*s) {
                    Ok(_) => {},
                    Err(e) => {
                        println!("Worker thread exiting with send error {}", e);
                        return;
                    },
                }
            }
            samples.clear();
        }
    }
}

/// Hand the workers their own send endpoints to communicate results back
/// to the main thread but drop the sender on the main thread so once
/// all threads finish the channel closes
fn spawn_workers(pool: &TaskPool, n: uint) -> Receiver<(f32, f32, film::Colorf)> {
    let (tx, rx) = mpsc::channel();
    let block_queue = Arc::new(sampler::BlockQueue::new((WIDTH as u32, HEIGHT as u32), (8, 8)));
    for _ in range(0, n) {
        let q = block_queue.clone();
        let t = tx.clone();
        pool.execute(move || {
            thread_work(t, q);
        });
    }
    rx
}

fn test_parallel(){
    let mut rt = film::RenderTarget::new(WIDTH, HEIGHT);
    let n = 8;
    let pool = TaskPool::new(n);
    let rx = spawn_workers(&pool, n);
    for m in rx.iter() {
        rt.write(m.0, m.1, &m.2);
    }
    film::write_ppm("out.ppm", WIDTH, HEIGHT, rt.get_render().as_slice());
}

fn main() {
    let d = Duration::span(move || test_parallel());
    println!("Rendering took {}ms", d.num_milliseconds());
    /*
    let block_queue = sampler::BlockQueue::new((width as u32, height as u32), (8, 8));
    let mut sampler = sampler::Uniform::new(block_queue.block_dim());
    let mut sample_pos = Vec::with_capacity(sampler.max_spp());
    for b in block_queue.iter() {
        sampler.select_block(&b);
        while sampler.has_samples() {
            sampler.get_samples(&mut sample_pos);
            for px in sample_pos.iter() {
                let mut ray = camera.generate_ray(*px);
                match instance.intersect(&mut ray) {
                    Some(_) => rt.write(px.0, px.1, &film::Colorf::broadcast(1.0)),
                    None => rt.write(px.0, px.1, &film::Colorf::new(0.0, 0.0, 1.0)),
                }
            }
        }
    }
    */

}

<|endoftext|>


<commit_before>extern crate nalgebra;

mod cube;
mod resource;

use cube::*;

fn main() {
    let point = Point::new(1024, 197, 293);
    let mut tree = Tree::new(10);
    {
        let mut cube = tree.cursor_mut();
        let mut cube = cube.subdivide().unwrap().resolve(&point, 0);
        let mut cube = cube.subdivide().unwrap().resolve(&point, 0);
        let mut cube = cube.subdivide().unwrap().resolve(&point, 0);
        cube.subdivide().unwrap();
    }
    let cube = tree.cursor().resolve(&point, 0);
    println!("{:?}", cube.partition().origin());
}
<commit_msg>Print width and origin of cubes.<commit_after>extern crate nalgebra;

mod cube;
mod render;
mod resource;

use cube::*;

fn main() {
    let point = Point::new(1024, 197, 293);
    let mut tree = Tree::new(10);
    {
        let mut cube = tree.cursor_mut();
        let mut cube = cube.subdivide().unwrap().resolve(&point, 0);
        let mut cube = cube.subdivide().unwrap().resolve(&point, 0);
        let mut cube = cube.subdivide().unwrap().resolve(&point, 0);
        cube.subdivide().unwrap();
    }
    for cube in tree.cursor().iter().filter(|cube| cube.is_leaf()) {
        println!("{}W at {}",
                 cube.partition().width(),
                 cube.partition().origin());
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

#[macro_use]
extern crate clap;
extern crate requests;
extern crate serde;
extern crate serde_json;

use clap::{App, SubCommand, AppSettings, ArgMatches};
mod crates;

const CARGO: &'static str = "cargo";

#[derive(Debug, PartialEq)]
enum Flags {
    Repository,
    Documentation,
    Downloads,
    Homepage,
    Default,
}

#[derive(Debug)]
struct Report {
    flags: Vec<Flags>,
    verbose: bool,
}

impl Report {
    pub fn new(info: &ArgMatches) -> Self {

        let mut flags: Vec<Flags> = vec![];
        if info.is_present("repository") {
            flags.push(Flags::Repository);
        }
        if info.is_present("documentation") {
            flags.push(Flags::Documentation);
        }
        if info.is_present("downloads") {
            flags.push(Flags::Downloads);
        }
        if info.is_present("homepage") {
            flags.push(Flags::Homepage);
        }

        if flags.is_empty() {
            flags.push(Flags::Default);
        }

        Report {
            flags: flags,
            verbose: info.is_present("verbose"),
        }
    }

    pub fn report(&self, name: &str) {
        if let Some(krate) = query(name).map(|r| r.krate) {
            for flag in &self.flags {
                match *flag {
                    Flags::Repository => krate.print_repository(self.verbose),
                    Flags::Documentation => krate.print_documentation(self.verbose),
                    Flags::Downloads => krate.print_downloads(self.verbose),
                    Flags::Homepage => krate.print_homepage(self.verbose),
                        Flags::Default => reportv(&krate, self.verbose),
                }
            }
        }
    }
}

fn reportv(krate: &crates::Crate, verbose: bool) {
    if verbose {
        println!("{:#}", krate);
    } else {
        println!("{}", krate);
    }
}

fn query(krate: &str) -> Option<crates::Reply> {
    let response = requests::get(&format!("http://crates.io/api/v1/crates/{}", krate)).unwrap();
    // println!("{:?}", response.json().unwrap());
    response.from_json::<crates::Reply>()
}

// use std::fmt;
// fn debug<T>(item: &T)
//     where T: fmt::Debug
// {
//     println!("{:#?}", item);
// }

fn main() {

    let matches = App::new(CARGO)
        .bin_name(CARGO)
        .author(crate_authors!())
        .version(crate_version!())
        .about("Queries registry for crates details")
        .setting(AppSettings::GlobalVersion)
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .subcommand(SubCommand::with_name("info")
            .setting(AppSettings::ArgRequiredElseHelp)
            .setting(AppSettings::TrailingVarArg)
            .arg_from_usage("-d, --documentation 'Report documentation URL'")
            .arg_from_usage("-D, --downloads 'Report number of crate downloads'")
            .arg_from_usage("-H, --homepage 'Report home page URL'")
            .arg_from_usage("-r, --repository 'Report crate repository URL'")
            .arg_from_usage("-v, --verbose 'Provides more info'")
            .arg_from_usage("<crate>... 'crate to query'"))
        .get_matches();

    if let Some(info) = matches.subcommand_matches("info") {
        if let Some(crates) = info.values_of("crate") {
            let rep = Report::new(info);
            for krate in crates {
                // debug(&krate);
                rep.report(krate);
            }
        }
    }
}
<commit_msg>Rename Flags -> Flag<commit_after>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

#[macro_use]
extern crate clap;
extern crate requests;
extern crate serde;
extern crate serde_json;

use clap::{App, SubCommand, AppSettings, ArgMatches};
mod crates;

const CARGO: &'static str = "cargo";

#[derive(Debug, PartialEq)]
enum Flag {
    Repository,
    Documentation,
    Downloads,
    Homepage,
    Default,
}

#[derive(Debug)]
struct Report {
    flags: Vec<Flag>,
    verbose: bool,
}

impl Report {
    pub fn new(info: &ArgMatches) -> Self {

        let mut flags: Vec<Flag> = vec![];
        if info.is_present("repository") {
            flags.push(Flag::Repository);
        }
        if info.is_present("documentation") {
            flags.push(Flag::Documentation);
        }
        if info.is_present("downloads") {
            flags.push(Flag::Downloads);
        }
        if info.is_present("homepage") {
            flags.push(Flag::Homepage);
        }

        if flags.is_empty() {
            flags.push(Flag::Default);
        }

        Report {
            flags: flags,
            verbose: info.is_present("verbose"),
        }
    }

    pub fn report(&self, name: &str) {
        if let Some(krate) = query(name).map(|r| r.krate) {
            for flag in &self.flags {
                match *flag {
                    Flag::Repository => krate.print_repository(self.verbose),
                    Flag::Documentation => krate.print_documentation(self.verbose),
                    Flag::Downloads => krate.print_downloads(self.verbose),
                    Flag::Homepage => krate.print_homepage(self.verbose),
                        Flag::Default => reportv(&krate, self.verbose),
                }
            }
        }
    }
}

fn reportv(krate: &crates::Crate, verbose: bool) {
    if verbose {
        println!("{:#}", krate);
    } else {
        println!("{}", krate);
    }
}

fn query(krate: &str) -> Option<crates::Reply> {
    let response = requests::get(&format!("http://crates.io/api/v1/crates/{}", krate)).unwrap();
    // println!("{:?}", response.json().unwrap());
    response.from_json::<crates::Reply>()
}

// use std::fmt;
// fn debug<T>(item: &T)
//     where T: fmt::Debug
// {
//     println!("{:#?}", item);
// }

fn main() {

    let matches = App::new(CARGO)
        .bin_name(CARGO)
        .author(crate_authors!())
        .version(crate_version!())
        .about("Queries registry for crates details")
        .setting(AppSettings::GlobalVersion)
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .subcommand(SubCommand::with_name("info")
            .setting(AppSettings::ArgRequiredElseHelp)
            .setting(AppSettings::TrailingVarArg)
            .arg_from_usage("-d, --documentation 'Report documentation URL'")
            .arg_from_usage("-D, --downloads 'Report number of crate downloads'")
            .arg_from_usage("-H, --homepage 'Report home page URL'")
            .arg_from_usage("-r, --repository 'Report crate repository URL'")
            .arg_from_usage("-v, --verbose 'Provides more info'")
            .arg_from_usage("<crate>... 'crate to query'"))
        .get_matches();

    if let Some(info) = matches.subcommand_matches("info") {
        if let Some(crates) = info.values_of("crate") {
            let rep = Report::new(info);
            for krate in crates {
                // debug(&krate);
                rep.report(krate);
            }
        }
    }
}
<|endoftext|>