<commit_before>#[macro_use] extern crate glium;
#[macro_use] extern crate imgui;
extern crate image;
extern crate nalgebra;
extern crate time;

use std::io::Cursor;

use glium::glutin::{ElementState, Event, MouseButton, VirtualKeyCode};
use glium::{glutin, DisplayBuild, Surface};
use image::GenericImage;
use imgui::ImGui;
use imgui::glium_renderer::Renderer;
use nalgebra::Vec2;
use time::{SteadyTime, Duration};

#[derive(Copy, Clone)]
struct Vertex {
    in_pos: Vec2<f32>,
}

implement_vertex!(Vertex, in_pos);

impl Vertex {
    fn new(x: f32, y: f32) -> Vertex{
        Vertex { in_pos: Vec2::new(x, y) }
    }
}

struct Tunables {
    escape_threshold: f32,
    max_iteration: i32,
    speed: f32,
}

struct App {
    tunables: Tunables,
    scale: f32,
    position: Vec2<f32>,
    mouse_position: Vec2<f32>,
    mouse_down: bool,
    last_frame: Option<SteadyTime>,
    delta: Option<Duration>,
}

impl App {
    fn new() -> App {
        App {
            tunables: Tunables {
                escape_threshold: 4.0,
                max_iteration: 100,
                speed: 0.1,
            },
            scale: 1.0,
            position: Vec2::new(0.0, 0.0),
            mouse_position: Vec2::new(0.0, 0.0),
            mouse_down: false,
            last_frame: None,
            delta: None,
        }
    }

    fn frame(&mut self) {
        let now = SteadyTime::now();
        if let Some(t) = self.last_frame {
            self.delta = Some(now - t);
        }

        self.last_frame = Some(now)
    }

    fn frame_delta_seconds(&self) -> Option<f32> {
        self.delta.map(|d| d.num_nanoseconds().unwrap() as f32 / 1_000_000_000.0)
    }

    fn handle_key(&mut self, code: glutin::VirtualKeyCode) {
        let speed = self.tunables.speed;
        match code {
            glutin::VirtualKeyCode::J => self.scale *= 1.0 + speed,
            glutin::VirtualKeyCode::K => self.scale *= 1.0 - speed,
            glutin::VirtualKeyCode::W => self.position.y += speed * self.scale,
            glutin::VirtualKeyCode::S => self.position.y -= speed * self.scale,
            glutin::VirtualKeyCode::A => self.position.x -= speed * self.scale,
            glutin::VirtualKeyCode::D => self.position.x += speed * self.scale,
            _ => ()
        }
    }

    fn handle_mouse_move(&mut self, x: f32, y: f32) {
        let new_position = Vec2::new(x, y);
        if self.mouse_down {
            let diff = new_position - self.mouse_position;
            self.position = self.position - diff * self.scale;
        }

        self.mouse_position = new_position;
    }

    fn handle_mouse_click(&mut self, clicked: bool) {
        self.mouse_down = clicked
    }

    fn handle_scroll(&mut self, amount: f32) {
        let point_at = self.position + self.mouse_position * self.scale;
        let x = 0.999f32;
        self.scale *= x.powf(amount);
        self.position = point_at - self.mouse_position * self.scale;
    }
}

fn mandelbrot() {
    let display = glutin::WindowBuilder::new()
        .with_dimensions(800, 800)
        .with_depth_buffer(24)
        .with_gl_profile(glutin::GlProfile::Core)
        .build_glium().unwrap();

    let mut imgui = ImGui::init();
    imgui.set_ini_filename(None);
    let mut renderer = Renderer::init(&mut imgui, &display).unwrap();

    let shape = vec![Vertex::new(-1.0, -1.0),
                     Vertex::new(-1.0,  1.0),
                     Vertex::new( 1.0,  1.0),
                     Vertex::new(-1.0, -1.0),
                     Vertex::new( 1.0, -1.0),
                     Vertex::new( 1.0,  1.0),
                     ];

    let vertex_buffer = glium::VertexBuffer::new(&display, &shape).unwrap();
    let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

    let image = image::load(Cursor::new(&include_bytes!("./texture.png")[..]),
                            image::PNG).unwrap();
    let pixels: Vec<_> = image.pixels().map(|(_, _, p)| p).collect();
    let texture = glium::texture::Texture1d::new(&display, pixels).unwrap();

    let program = glium::Program::from_source(&display,
                                              &include_str!("./shaders/vertex.glsl"),
                                              &include_str!("./shaders/fragment.glsl"),
                                              None).unwrap();

    let mut app = App::new();
    loop {
        let mut target = display.draw();
        let (width, height) = target.get_dimensions();

        for ev in display.poll_events() {
            match ev {
                Event::Closed => return,
                Event::KeyboardInput(ElementState::Pressed, _code, Some(key_code)) => {
                    app.handle_key(key_code);
                }
                Event::MouseMoved(pos) => {
                    imgui.set_mouse_pos(pos.0 as f32, pos.1 as f32);
                    app.handle_mouse_move(2.0 * (pos.0 as f32 / width as f32) - 1.0,
                                          -(2.0 * (pos.1 as f32 / height as f32) - 1.0));
                }
                Event::MouseWheel(delta) => {
                    match delta {
                        glutin::MouseScrollDelta::LineDelta(_, y) |
                        glutin::MouseScrollDelta::PixelDelta(_, y) => {
                            app.handle_scroll(y);
                        }
                    }
                }
                Event::MouseInput(state, MouseButton::Left) => {
                    imgui.set_mouse_down(&[state == ElementState::Pressed,
                                           false, false, false, false]);
                    app.handle_mouse_click(state == ElementState::Pressed);
                }
                _ => ()
            }
        }
        app.frame();
        target.clear_color(0.0, 0.0, 1.0, 1.0);
        let uniforms = uniform! {
            escape_threshold: app.tunables.escape_threshold,
            max_iteration: app.tunables.max_iteration as u32,
            position: app.position,
            scale: app.scale,
            tex: &texture,
        };
        target.draw(&vertex_buffer, &indices, &program, &uniforms,
                    &Default::default()).unwrap();
        let fps = format!("FPS: {}", imgui.get_frame_rate());
        let ifps = format!("ms per frame: {}", 1000.0 / imgui.get_frame_rate());

        let ui = imgui.frame(width, height, app.frame_delta_seconds().unwrap_or(1.0 / 60.0));
        ui.window()
            .name(im_str!("Hello world"))
            .movable(true)
            .size((500.0, 160.0), imgui::ImGuiSetCond_FirstUseEver)
            .build(|| {
                ui.text(im_str!("w, s, a, d, drag - movement\nj, k, wheel - scale."));
                ui.text(fps.into());
                ui.text(ifps.into());
                ui.slider_i32(im_str!("Number of iterations"),
                              &mut app.tunables.max_iteration, 0, 1000).build();
                ui.slider_f32(im_str!("Escape threshold"),
                              &mut app.tunables.escape_threshold, 0.0, 10.0).build();
            });
        renderer.render(&mut target, ui).unwrap();
        target.finish().unwrap();
    }
}

fn main() {
    mandelbrot();
}
<commit_msg>let imgui capture the mouse<commit_after>#[macro_use] extern crate glium;
#[macro_use] extern crate imgui;
extern crate image;
extern crate nalgebra;
extern crate time;

use std::io::Cursor;

use glium::glutin::{ElementState, Event, MouseButton, VirtualKeyCode};
use glium::{glutin, DisplayBuild, Surface};
use image::GenericImage;
use imgui::ImGui;
use imgui::glium_renderer::Renderer;
use nalgebra::Vec2;
use time::{SteadyTime, Duration};

#[derive(Copy, Clone)]
struct Vertex {
    in_pos: Vec2<f32>,
}

implement_vertex!(Vertex, in_pos);

impl Vertex {
    fn new(x: f32, y: f32) -> Vertex{
        Vertex { in_pos: Vec2::new(x, y) }
    }
}

struct Tunables {
    escape_threshold: f32,
    max_iteration: i32,
    speed: f32,
}

struct App {
    tunables: Tunables,
    scale: f32,
    position: Vec2<f32>,
    mouse_position: Vec2<f32>,
    mouse_down: bool,
    last_frame: Option<SteadyTime>,
    delta: Option<Duration>,
}

impl App {
    fn new() -> App {
        App {
            tunables: Tunables {
                escape_threshold: 4.0,
                max_iteration: 100,
                speed: 0.1,
            },
            scale: 1.0,
            position: Vec2::new(0.0, 0.0),
            mouse_position: Vec2::new(0.0, 0.0),
            mouse_down: false,
            last_frame: None,
            delta: None,
        }
    }

    fn frame(&mut self) {
        let now = SteadyTime::now();
        if let Some(t) = self.last_frame {
            self.delta = Some(now - t);
        }

        self.last_frame = Some(now)
    }

    fn frame_delta_seconds(&self) -> Option<f32> {
        self.delta.map(|d| d.num_nanoseconds().unwrap() as f32 / 1_000_000_000.0)
    }

    fn handle_key(&mut self, code: glutin::VirtualKeyCode) {
        let speed = self.tunables.speed;
        match code {
            glutin::VirtualKeyCode::J => self.scale *= 1.0 + speed,
            glutin::VirtualKeyCode::K => self.scale *= 1.0 - speed,
            glutin::VirtualKeyCode::W => self.position.y += speed * self.scale,
            glutin::VirtualKeyCode::S => self.position.y -= speed * self.scale,
            glutin::VirtualKeyCode::A => self.position.x -= speed * self.scale,
            glutin::VirtualKeyCode::D => self.position.x += speed * self.scale,
            _ => ()
        }
    }

    fn handle_mouse_move(&mut self, x: f32, y: f32) {
        let new_position = Vec2::new(x, y);
        if self.mouse_down {
            let diff = new_position - self.mouse_position;
            self.position = self.position - diff * self.scale;
        }

        self.mouse_position = new_position;
    }

    fn handle_mouse_click(&mut self, clicked: bool) {
        self.mouse_down = clicked
    }

    fn handle_scroll(&mut self, amount: f32) {
        let point_at = self.position + self.mouse_position * self.scale;
        let x = 0.999f32;
        self.scale *= x.powf(amount);
        self.position = point_at - self.mouse_position * self.scale;
    }
}

fn mandelbrot() {
    let display = glutin::WindowBuilder::new()
        .with_dimensions(800, 800)
        .with_depth_buffer(24)
        .with_gl_profile(glutin::GlProfile::Core)
        .build_glium().unwrap();

    let mut imgui = ImGui::init();
    imgui.set_ini_filename(None);
    let mut renderer = Renderer::init(&mut imgui, &display).unwrap();

    let shape = vec![Vertex::new(-1.0, -1.0),
                     Vertex::new(-1.0,  1.0),
                     Vertex::new( 1.0,  1.0),
                     Vertex::new(-1.0, -1.0),
                     Vertex::new( 1.0, -1.0),
                     Vertex::new( 1.0,  1.0),
                     ];

    let vertex_buffer = glium::VertexBuffer::new(&display, &shape).unwrap();
    let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

    let image = image::load(Cursor::new(&include_bytes!("./texture.png")[..]),
                            image::PNG).unwrap();
    let pixels: Vec<_> = image.pixels().map(|(_, _, p)| p).collect();
    let texture = glium::texture::Texture1d::new(&display, pixels).unwrap();

    let program = glium::Program::from_source(&display,
                                              &include_str!("./shaders/vertex.glsl"),
                                              &include_str!("./shaders/fragment.glsl"),
                                              None).unwrap();

    let mut app = App::new();
    loop {
        let mut target = display.draw();
        let (width, height) = target.get_dimensions();
        let mut mouse_pos = None;
        for ev in display.poll_events() {
            match ev {
                Event::Closed => return,
                Event::KeyboardInput(ElementState::Pressed, _code, Some(key_code)) => {
                    app.handle_key(key_code);
                }
                Event::MouseMoved(pos) => {
                    imgui.set_mouse_pos(pos.0 as f32, pos.1 as f32);
                    mouse_pos = Some(pos)
                }
                Event::MouseWheel(delta) => {
                    match delta {
                        glutin::MouseScrollDelta::LineDelta(_, y) |
                        glutin::MouseScrollDelta::PixelDelta(_, y) => {
                            app.handle_scroll(y)
                        }
                    }
                }
                Event::MouseInput(state, MouseButton::Left) => {
                    imgui.set_mouse_down(&[state == ElementState::Pressed,
                                           false, false, false, false]);
                    app.handle_mouse_click(state == ElementState::Pressed);
                }
                _ => ()
            }
        }
        app.frame();
        target.clear_color(0.0, 0.0, 1.0, 1.0);
        let uniforms = uniform! {
            escape_threshold: app.tunables.escape_threshold,
            max_iteration: app.tunables.max_iteration as u32,
            position: app.position,
            scale: app.scale,
            tex: &texture,
        };
        target.draw(&vertex_buffer, &indices, &program, &uniforms,
                    &Default::default()).unwrap();
        let fps = format!("FPS: {}", imgui.get_frame_rate());
        let ifps = format!("ms per frame: {}", 1000.0 / imgui.get_frame_rate());

        let ui = imgui.frame(width, height, app.frame_delta_seconds().unwrap_or(1.0 / 60.0));
        if !ui.want_capture_mouse() {
            if let Some(pos) = mouse_pos {
                app.handle_mouse_move(2.0 * (pos.0 as f32 / width as f32) - 1.0,
                                      -(2.0 * (pos.1 as f32 / height as f32) - 1.0));
            }
        }
        ui.window()
            .name(im_str!("I'm a little fractal"))
            .movable(true)
            .size((500.0, 160.0), imgui::ImGuiSetCond_FirstUseEver)
            .build(|| {
                ui.text(im_str!("w, s, a, d, drag - movement\nj, k, wheel - scale."));
                ui.text(fps.into());
                ui.text(ifps.into());
                ui.separator();
                ui.slider_i32(im_str!("Number of iterations"),
                              &mut app.tunables.max_iteration, 0, 1000).build();
                ui.slider_f32(im_str!("Escape threshold"),
                              &mut app.tunables.escape_threshold, 0.0, 10.0).build();
            });
        renderer.render(&mut target, ui).unwrap();
        target.finish().unwrap();
    }
}

fn main() {
    mandelbrot();
}
<|endoftext|>


<commit_before>#![feature(vec_push_all)]

use self::pair::*;
use self::Leading::*;

mod pair;

#[derive(Copy, Clone)]
enum Leading {
    Top,
    Bot,
}

impl Leading {
    pub fn switched(self) -> Leading {
        match self {
            Top => Bot,
            Bot => Top,
        }
    }
}

struct Problem {
    pairs: Box<[SPair]>,
}

fn main() {
    let p = Problem::from([("010", "0"), ("0", "01"), ("101", "0100")].as_ref());
}

impl<'a> From<&'a [(&'a str, &'a str)]> for Problem {
    fn from(s: &'a [(&'a str, &'a str)]) -> Problem {
        let mut pairs = Vec::with_capacity(s.len());

        for &p in s {
            pairs.push(p.into());
        }

        Problem {
            pairs: pairs.into_boxed_slice(),
        }
    }
}
<commit_msg>implement solve<commit_after>#![feature(vec_push_all)]

use std::{cmp, mem};

use self::pair::*;
use self::Leading::*;

mod pair;

#[derive(Copy, Clone)]
enum Leading {
    Top,
    Bot,
}

impl Leading {
    pub fn switched(self) -> Leading {
        match self {
            Top => Bot,
            Bot => Top,
        }
    }
}

struct Problem {
    pairs: Box<[SPair]>,
}

impl Problem {
    fn solve(&self, max_depth: u32) {
        let mut depth = 0;
        let mut max_set_size = 0;

        let mut current_working_set = Vec::new();
        let mut next_working_set = Vec::new();

        current_working_set.push(VPair::new());

        while depth <= max_depth {
            println!("Now at depth {}", depth);
            max_set_size = cmp::max(max_set_size, current_working_set.len());

            for e in current_working_set.iter() {
                for p in self.pairs.iter() {
                    if let Some(ne) = e.apply(p) {
                        if ne.is_complete() {
                            println!("success!");
                            println!("max set: {}", max_set_size);
                            return;
                        }

                        next_working_set.push(ne);
                    }
                }
            }

            mem::swap(&mut current_working_set, &mut next_working_set);
            next_working_set.clear();

            depth += 1;
        }
        println!("no success");
    }
}

fn main() {
    let p = Problem::from([("010", "0"), ("0", "01"), ("101", "0100")].as_ref());
    // let p = Problem::from([("1", "101"), ("10", "00"), ("011", "11")].as_ref());
    // let p = Problem::from([("001", "0"), ("01", "011"), ("01", "101"), ("10", "001")].as_ref());
    p.solve(300);
}

impl<'a> From<&'a [(&'a str, &'a str)]> for Problem {
    fn from(s: &'a [(&'a str, &'a str)]) -> Problem {
        let mut pairs = Vec::with_capacity(s.len());

        for &p in s {
            pairs.push(p.into());
        }

        Problem {
            pairs: pairs.into_boxed_slice(),
        }
    }
}
<|endoftext|>


<commit_before>// UDP stuff adapted from http://illegalargumentexception.blogspot.co.uk/2015/05/rust-send-and-receive-on-localhost-with.html
use std::thread;
use std::net;
use std::env;
use std::convert::AsRef;
extern crate getopts;
use getopts::Options;

fn socket(listen_on: net::SocketAddr) -> net::UdpSocket {
    let attempt = net::UdpSocket::bind(listen_on);
    let mut socket;
    match attempt {
        Ok(sock) => {
            socket = sock;
        },
    Err(err) => panic!("Could not bind: {}", err)
    }
    socket
}

fn read_message(socket: net::UdpSocket) -> Vec<u8> {
    let mut buf: [u8; 1] = [0; 1];
    let result = socket.recv_from(&mut buf);
    drop(socket);
    let mut data;
    match result {
        Ok((amt, _)) => {
        data = Vec::from(&buf[0..amt]);
        },
    Err(err) => panic!("Read error: {}", err)
    }
    data
}

pub fn send_message(send_addr: net::SocketAddr, target: net::SocketAddr, data: Vec<u8>) {
    let socket = socket(send_addr);
    let _ = socket.send_to(&data, target);
    drop(socket);
}

pub fn listen(listen_on: net::SocketAddr) -> thread::JoinHandle<Vec<u8>> {
    let socket = socket(listen_on);
    let handle = thread::spawn(move || {
        read_message(socket)
    });
    handle
}

#[cfg(test)]
mod test {
    use std::net;
    use std::thread;
    use super::*;

    #[test]
    fn test_udp() {
        println!("UDP");
        let ip = net::Ipv4Addr::new(127, 0, 0, 1);
        let listen_addr = net::SocketAddrV4::new(ip, 8888);
        let send_addr = net::SocketAddrV4::new(ip, 8889);
        let future = listen(net::SocketAddr::V4(listen_addr));
        let message: Vec<u8> = vec![10];
        // give the thread 3s to open the socket
        thread::sleep_ms(3000);
        send_message(
            net::SocketAddr::V4(send_addr),
            net::SocketAddr::V4(listen_addr),
            message);
        println!("Waiting");
        let received = future.join().unwrap();
        println!("Got {} bytes", received.len());
        assert_eq!(1, received.len());
        assert_eq!(10, received[0]);
    }
}

fn convert(inp: &str) -> String {
    // to_lowercase is still unstable.
    // This madness from IRC is the workaround
    // works though
    let outp = inp
        .chars()
        .flat_map(char::to_lowercase)
        .collect::<String>();
    outp
}

fn print_usage(program: &str, opts: Options, ecode: i32) {
    let brief = format!("Usage: {} [options] [command]", program);
    print!("{}", opts.usage(&brief));
    exit(ecode);
}

pub fn exit(code: i32) {
    std::process::exit(code)
}

fn main() {
    let mut opts = Options::new();
    // get command-line input
    // Strings do not live for the entire life of your program
    // http://stackoverflow.com/a/23977218/416626
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    opts.optopt("p", "port", "Set destination UDP port. Must be an integer.", "PORT");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => {m}
        Err(f) => {panic!(f.to_string())}
    };
    // Get port from the option, or specify the default
    let port = matches.opt_str("p").unwrap_or("1738".to_string());
    // cast to int and ensure it worked, or set an error flag and bail out
    let numeric_port = port.parse::<u16>();
    let proceed = match numeric_port {
        Ok(ref v) => true,
        Err(ref e) => false
    };
    if !proceed {
        print_usage(&program, opts, 1);
        return;
    }
    // gather non-option arguments
    let arg = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts, 0);
        return;
    };
    let intermediate: &str = &*arg;

    // match command-line input or bail out horribly
    let to_send = match convert(intermediate).as_ref() {
        "white" => "white".to_string(),
        "red" => "red".to_string(),
        "orange" => "orange".to_string(),
        "yellow" => "yellow".to_string(),
        "green" => "green".to_string(),
        "cyan" => "cyan".to_string(),
        "blue" => "blue".to_string(),
        "purple" => "purple".to_string(),
        "black" => "black".to_string(),
        "?" => "question".to_string(),
        "!" => "exclamation".to_string(),
        "quit" => "quit".to_string(),
        _ => {
            print_usage(&program, opts, 1);
            return;
        }
    };
    // blam our control message into a vector
    let mut message: Vec<u8> = Vec::new();
    message.extend(to_send
        .as_bytes()
        .iter()
        .cloned()
    );
    // bind to the correct UDP port
    let ip = net::Ipv4Addr::new(127, 0, 0, 1);
    // parse() gives us Result which we need to unwrap
    // it's safe to unwrap here, cos we already checked success with
    let listen_addr = net::SocketAddrV4::new(ip, numeric_port.unwrap());
    let send_addr = net::SocketAddrV4::new(ip, 0);
    // and send our message
    send_message(
        net::SocketAddr::V4(send_addr),
        net::SocketAddr::V4(listen_addr),
        message);
}
<commit_msg>Simplify early exit functionality<commit_after>// UDP stuff adapted from http://illegalargumentexception.blogspot.co.uk/2015/05/rust-send-and-receive-on-localhost-with.html
use std::thread;
use std::net;
use std::env;
use std::convert::AsRef;
extern crate getopts;
use getopts::Options;

fn socket(listen_on: net::SocketAddr) -> net::UdpSocket {
    let attempt = net::UdpSocket::bind(listen_on);
    let mut socket;
    match attempt {
        Ok(sock) => {
            socket = sock;
        },
    Err(err) => panic!("Could not bind: {}", err)
    }
    socket
}

fn read_message(socket: net::UdpSocket) -> Vec<u8> {
    let mut buf: [u8; 1] = [0; 1];
    let result = socket.recv_from(&mut buf);
    drop(socket);
    let mut data;
    match result {
        Ok((amt, _)) => {
        data = Vec::from(&buf[0..amt]);
        },
    Err(err) => panic!("Read error: {}", err)
    }
    data
}

pub fn send_message(send_addr: net::SocketAddr, target: net::SocketAddr, data: Vec<u8>) {
    let socket = socket(send_addr);
    let _ = socket.send_to(&data, target);
    drop(socket);
}

pub fn listen(listen_on: net::SocketAddr) -> thread::JoinHandle<Vec<u8>> {
    let socket = socket(listen_on);
    let handle = thread::spawn(move || {
        read_message(socket)
    });
    handle
}

#[cfg(test)]
mod test {
    use std::net;
    use std::thread;
    use super::*;

    #[test]
    fn test_udp() {
        println!("UDP");
        let ip = net::Ipv4Addr::new(127, 0, 0, 1);
        let listen_addr = net::SocketAddrV4::new(ip, 8888);
        let send_addr = net::SocketAddrV4::new(ip, 8889);
        let future = listen(net::SocketAddr::V4(listen_addr));
        let message: Vec<u8> = vec![10];
        // give the thread 3s to open the socket
        thread::sleep_ms(3000);
        send_message(
            net::SocketAddr::V4(send_addr),
            net::SocketAddr::V4(listen_addr),
            message);
        println!("Waiting");
        let received = future.join().unwrap();
        println!("Got {} bytes", received.len());
        assert_eq!(1, received.len());
        assert_eq!(10, received[0]);
    }
}

fn convert(inp: &str) -> String {
    // to_lowercase is still unstable.
    // This madness from IRC is the workaround
    // works though
    let outp = inp
        .chars()
        .flat_map(char::to_lowercase)
        .collect::<String>();
    outp
}

fn print_usage(program: &str, opts: Options, ecode: i32) {
    let brief = format!("Usage: {} [options] [command]", program);
    print!("{}", opts.usage(&brief));
    std::process::exit(ecode);
}

fn main() {
    let mut opts = Options::new();
    // get command-line input
    // Strings do not live for the entire life of your program
    // http://stackoverflow.com/a/23977218/416626
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    opts.optopt("p", "port", "Set destination UDP port. Must be an integer.", "PORT");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => {m}
        Err(f) => {panic!(f.to_string())}
    };
    // Get port from the option, or specify the default
    let port = matches.opt_str("p").unwrap_or("1738".to_string());
    // cast to int and ensure it worked, or set an error flag and bail out
    let numeric_port = port.parse::<u16>();
    let proceed = match numeric_port {
        Ok(ref v) => true,
        Err(ref e) => false
    };
    if !proceed {
        print_usage(&program, opts, 1);
        return;
    }
    // gather non-option arguments
    let arg = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts, 0);
        return;
    };
    let intermediate: &str = &*arg;

    // match command-line input or bail out horribly
    let to_send = match convert(intermediate).as_ref() {
        "white" => "white".to_string(),
        "red" => "red".to_string(),
        "orange" => "orange".to_string(),
        "yellow" => "yellow".to_string(),
        "green" => "green".to_string(),
        "cyan" => "cyan".to_string(),
        "blue" => "blue".to_string(),
        "purple" => "purple".to_string(),
        "black" => "black".to_string(),
        "?" => "question".to_string(),
        "!" => "exclamation".to_string(),
        "quit" => "quit".to_string(),
        _ => {
            print_usage(&program, opts, 1);
            return;
        }
    };
    // blam our control message into a vector
    let mut message: Vec<u8> = Vec::new();
    message.extend(to_send
        .as_bytes()
        .iter()
        .cloned()
    );
    // bind to the correct UDP port
    let ip = net::Ipv4Addr::new(127, 0, 0, 1);
    // parse() gives us Result which we need to unwrap
    // it's safe to unwrap here, cos we already checked success with
    let listen_addr = net::SocketAddrV4::new(ip, numeric_port.unwrap());
    let send_addr = net::SocketAddrV4::new(ip, 0);
    // and send our message
    send_message(
        net::SocketAddr::V4(send_addr),
        net::SocketAddr::V4(listen_addr),
        message);
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate rustc_serialize;
extern crate chrono;
extern crate regex;

use chrono::*;

use rustc_serialize::json;
use std::io::Read;
use hyper::client::Client;
use regex::Regex;

struct Session {
    api_key: &'static str,
}

impl Session {
    fn new(api_key: &'static str) -> Session {
        Session { api_key: api_key }
    }

    fn url(&self, path: &str) -> String {
        format!("http://www.wsdot.wa.gov/ferries/api/schedule/rest{}?apiaccesscode={}",
                path,
                self.api_key)
    }
}

#[allow(non_snake_case)]
#[derive(RustcDecodable, Debug)]
struct SailingTime {
    DepartingTime: String,
    ArrivingTime: Option<String>
}

impl SailingTime {
    // parse strings of form "/Date(1436318400000-0700)/"
    fn depart_time(&self, ltz: Local) -> DateTime<Local> {
        let re = Regex::new(r"^/Date\((\d{10})000-(\d{2})(\d{2})\)/$").unwrap();
        let caps = re.captures(&self.DepartingTime).unwrap();

        let epoch_s = caps.at(1).unwrap();
        let epoch: i64 =  epoch_s.parse().unwrap();

        let tzhs = caps.at(2).unwrap();
        let tzhi: i32 = tzhs.parse().unwrap();

        let tzms = caps.at(3).unwrap();
        let tzmi: i32 = tzms.parse().unwrap();

        let nd = NaiveDateTime::from_timestamp(epoch, 0);
        let tz = FixedOffset::west((tzhi * 3600) + (tzmi * 60));
        let fotz: DateTime<FixedOffset> = DateTime::from_utc(nd, tz);
        fotz.with_timezone(&ltz)
    }
}

#[allow(non_snake_case)]
#[derive(RustcDecodable, Debug)]
struct TerminalCombo {
    Times: Vec<SailingTime>,
}

#[allow(non_snake_case)]
#[derive(RustcDecodable, Debug)]
struct ScheduleResult {
    TerminalCombos: Vec<TerminalCombo>,
}

fn main() {
    let now = Local::now();
    let s = Session::new(env!("WSDOT_API_KEY"));
    let url = s.url("/schedule/2015-07-06/7/3");
    println!("{}", url);

    let client = Client::new();
    let mut res = client.get(&url).send().unwrap();

    assert_eq!(res.status, hyper::Ok);
    let mut s = String::new();
    res.read_to_string(&mut s).unwrap();
    let routes: ScheduleResult = json::decode(&s).unwrap();

    assert_eq!(1, routes.TerminalCombos.len());
    for time in routes.TerminalCombos[0].Times.iter() {
        let dt = time.depart_time(now.timezone());
        if dt > now {
            println!("{}", dt.time());
        }
    }
}

#[test]
fn test_regex() {
    // parse strings of form "/Date(1436318400000-0700)/"
    let re = Regex::new(r"^/Date\((\d{10})000-(\d{4})\)/$").unwrap();
    let caps = re.captures("/Date(1436318400000-0700)/").unwrap();
    assert_eq!(caps.at(1).unwrap(), "1436318400");
    assert_eq!(caps.at(2).unwrap(), "0700");
}
<commit_msg>go either way<commit_after>extern crate hyper;
extern crate rustc_serialize;
extern crate chrono;
extern crate regex;

use std::io::Read;
use std::env;

use chrono::*;
use rustc_serialize::json;
use hyper::client::Client;
use regex::Regex;

struct Session {
    api_key: &'static str,
}

impl Session {
    fn new(api_key: &'static str) -> Session {
        Session { api_key: api_key }
    }

    fn url(&self, path: String) -> String {
        format!("http://www.wsdot.wa.gov/ferries/api/schedule/rest{}?apiaccesscode={}",
                path,
                self.api_key)
    }
}

#[allow(non_snake_case)]
#[derive(RustcDecodable, Debug)]
struct SailingTime {
    DepartingTime: String,
    ArrivingTime: Option<String>
}

impl SailingTime {
    // parse strings of form "/Date(1436318400000-0700)/"
    fn depart_time(&self, ltz: Local) -> DateTime<Local> {
        let re = Regex::new(r"^/Date\((\d{10})000-(\d{2})(\d{2})\)/$").unwrap();
        let caps = re.captures(&self.DepartingTime).unwrap();

        let epoch_s = caps.at(1).unwrap();
        let epoch: i64 =  epoch_s.parse().unwrap();

        let tzhs = caps.at(2).unwrap();
        let tzhi: i32 = tzhs.parse().unwrap();

        let tzms = caps.at(3).unwrap();
        let tzmi: i32 = tzms.parse().unwrap();

        let nd = NaiveDateTime::from_timestamp(epoch, 0);
        let tz = FixedOffset::west((tzhi * 3600) + (tzmi * 60));
        let fotz: DateTime<FixedOffset> = DateTime::from_utc(nd, tz);
        fotz.with_timezone(&ltz)
    }
}

#[allow(non_snake_case)]
#[derive(RustcDecodable, Debug)]
struct TerminalCombo {
    Times: Vec<SailingTime>,
}

#[allow(non_snake_case)]
#[derive(RustcDecodable, Debug)]
struct ScheduleResult {
    TerminalCombos: Vec<TerminalCombo>,
}

fn main() {
    let mut args = env::args();
    let _program = args.next().unwrap();
    let route: &str = &args.next().expect("must pass one of sea-bi or bi-sea");

    let (from, to) = match route {
        "sea-bi" => (7,3),
        "bi-sea" => (3, 7),
        _ => panic!("only bi-sea and sea-bi supported"),
    };

    let now = Local::now();
    let s = Session::new(env!("WSDOT_API_KEY"));
    let url = &s.url(format!("/schedule/2015-07-06/{}/{}", from, to));
    // println!("{}", url);

    let client = Client::new();
    let mut res = client.get(url).send().unwrap();

    assert_eq!(res.status, hyper::Ok);
    let mut s = String::new();
    res.read_to_string(&mut s).unwrap();
    let routes: ScheduleResult = json::decode(&s).unwrap();

    assert_eq!(1, routes.TerminalCombos.len());
    for time in routes.TerminalCombos[0].Times.iter() {
        let dt = time.depart_time(now.timezone());
        if dt > now {
            println!("{}", dt.time());
        }
    }
}

#[test]
fn test_regex() {
    // parse strings of form "/Date(1436318400000-0700)/"
    let re = Regex::new(r"^/Date\((\d{10})000-(\d{4})\)/$").unwrap();
    let caps = re.captures("/Date(1436318400000-0700)/").unwrap();
    assert_eq!(caps.at(1).unwrap(), "1436318400");
    assert_eq!(caps.at(2).unwrap(), "0700");
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]

extern crate time;
extern crate serialize;

use scene::{Camera, Scene};

use std::io::File;
use std::io;
use std::os;
use std::sync::Arc;
use serialize::json;
use serialize::json::MissingFieldError;

mod geometry;
mod light;
mod material;
mod my_scene;
mod raytracer;
mod scene;
mod util;
mod vec3;
mod mat4;

// Replace this with argparse eventually
struct ProgramArgs {
    config_file: String
}

#[deriving(Decodable, Encodable)]
struct SceneConfig<'a> {
    name: String,
    size: (int, int),
    fov: f64,
    reflect_depth: uint,
    refract_depth: uint,
    shadow_samples: uint,
    pixel_samples: uint,
    output_file: String,
    animating: bool,
    fps: f64,
    time_slice: (f64, f64),
    starting_frame_number: uint
}

fn parse_args(args: Vec<String>) -> Result<ProgramArgs, String>  {
    let (program_name, rest) = match args.as_slice() {
        // I wouldn't expect this in the wild
        [] => fail!("Args do not even include a program name"),
        [ref program_name, ..rest] => (
            program_name,
            rest
        )
    };
    match rest.len() {
        0 => Err(format!("Usage: {} scene_config.json", program_name)),
        1 => Ok(ProgramArgs {
            config_file: rest[0].clone()
        }),
        _ => Err(format!("Usage: {} scene_config.json", program_name)),
    }
}

fn get_camera_and_scene(config: &SceneConfig) -> Option<(Camera, Scene)> {
    let scene_name = config.name.clone();
    let (image_width, image_height) = config.size;
    let fov = config.fov;

    // Cameras, scenes created in ./my_scene.rs
    // Scenes with an octree supplied (see my_scene.rs) will use it.
    // Lower the render quality (especially shadow_samples) for complex scenes
    return match scene_name.as_slice() {
        "box" => {
            // Box. Simplest scene with 9 primitives, no octree
            let camera = my_scene::cornell::get_camera(image_width, image_height, fov);
            let scene = my_scene::cornell::get_scene();
            Some((camera, scene))
        },
        "bunny" => {
            // Bunny. Around 300 primitives, 2 lights. Uses octree. Has skybox, textures are
            // in another repository.
            let camera = my_scene::bunny::get_camera(image_width, image_height, fov);
            let scene = my_scene::bunny::get_scene();
            Some((camera, scene))
        },
        "teapot" => {
            // Teapot. Around 2500 polygons. Octree helps a bit. Has skybox.
            let camera = my_scene::teapot::get_teapot_camera(image_width, image_height, fov);
            let scene = my_scene::teapot::get_teapot_scene();
            Some((camera, scene))
        },
        "cow" => {
            // Cow. Around 5000 polygons. Octree helps considerably.
            let camera = my_scene::cow::get_camera(image_width, image_height, fov);
            let scene = my_scene::cow::get_scene();
            Some((camera, scene))
        },
        "lucy" => {
            // Lucy. Around 525814+1 primitives. Octree pretty much required. The model is included
            // separately, in another repository. Has skybox.
            let camera = my_scene::lucy::get_camera(image_width, image_height, fov);
            let scene = my_scene::lucy::get_scene();
            Some((camera, scene))
        },
        "sponza" => {
            // Sponza. Around 28K triangles, but more complex than Lucy. 2 lights.
            let camera = my_scene::sponza::get_camera(image_width, image_height, fov);
            let scene = my_scene::sponza::get_scene();
            Some((camera, scene))
        },
        "sibenik" => {
            // Sibenik, around 70K triangles, no texture work, 3 lights.
            let camera = match config.animating {
                true => my_scene::sibenik::get_animation_camera(image_width, image_height, fov),
                false => my_scene::sibenik::get_camera(image_width, image_height, fov)
            };
            let scene = my_scene::sibenik::get_scene();
            Some((camera, scene))
        },
        "heptoroid-white" => {
            // Heptoroid, 114688 tris, 57302 verts
            let camera = my_scene::heptoroid::get_camera(image_width, image_height, fov);
            let scene = my_scene::heptoroid::get_scene("white");
            Some((camera, scene))
        },
        "heptoroid-shiny" => {
            // Shiny heptoroid, 114688 tris, 57302 verts
            let camera = my_scene::heptoroid::get_camera(image_width, image_height, fov);
            let scene = my_scene::heptoroid::get_scene("shiny");
            Some((camera, scene))
        },
        "heptoroid-refractive" => {
            // Refractive heptoroid, you want to limit your reflect levels (2/3?)
            // and up your refract levels (10/16?) for this
            let camera = my_scene::heptoroid::get_camera(image_width, image_height, fov);
            let scene = my_scene::heptoroid::get_scene("refractive");
            Some((camera, scene))
        },
        "tachikoma" => {
            // Shiny heptoroid, 114688 tris, 57302 verts
            // You can forget about refractions, it's too complex a scene
            let camera = my_scene::tachikoma::get_camera(image_width, image_height, fov);
            let scene = my_scene::tachikoma::get_scene();
            Some((camera, scene))
        },
        "sphere" => {
            // Sphere skybox test scene
            let camera = match config.animating {
                true => my_scene::sphere::get_animation_camera(image_width, image_height, fov),
                false => my_scene::sphere::get_camera(image_width, image_height, fov)
            };
            let scene = my_scene::sphere::get_scene();
            Some((camera, scene))
        },
        "fresnel" => {
            // Fresnel test scene
            let camera = match config.animating {
                true => my_scene::fresnel::get_animation_camera(image_width, image_height, fov),
                false => my_scene::fresnel::get_camera(image_width, image_height, fov)
            };
            let scene = my_scene::fresnel::get_scene();
            Some((camera, scene))
        },
        _ => None
    };
}

fn main() {
    let start_time = ::time::get_time().sec;

    let program_args = match parse_args(os::args()) {
        Ok(program_args) => program_args,
        Err(error_str) => {
            let mut stderr = io::stderr();
            assert!(stderr.write(error_str.append("\n").as_bytes()).is_ok());
            os::set_exit_status(1);
            return
        }
    };
    let config_path = Path::new(program_args.config_file);
    let mut file_handle = match File::open(&config_path) {
        Ok(file) => file,
        Err(err) => {
            let mut stderr = io::stderr();
            assert!(stderr.write(format!("{}", err).append("\n").as_bytes()).is_ok());
            os::set_exit_status(1);
            return
        }
    };
    let json_data = match file_handle.read_to_string() {
        Ok(data) => data,
        Err(err) => {
            let mut stderr = io::stderr();
            assert!(stderr.write(format!("{}", err).append("\n").as_bytes()).is_ok());
            os::set_exit_status(1);
            return
        }
    };

    let config: SceneConfig = match json::decode(json_data.as_slice()) {
        Ok(data) => data,
        Err(err) => {
            let mut stderr = io::stderr();
            let msg = match err {
                MissingFieldError(field_name) => {
                    format!("parse failure, missing field ``{}''\n", field_name)
                },
                _ => {
                    format!("parse failure: {}", err)
                }
            };
            assert!(stderr.write(msg.as_bytes()).is_ok());
            os::set_exit_status(1);
            return
        }
    };

    println!("Job started at {}...\nLoading scene...", start_time);

    let scenepair = get_camera_and_scene(&config);
    let (camera, scene) = match scenepair {
        Some(pair) => pair,
        None => {
            let mut stderr = io::stderr();
            let msg = format!("unknown scene ``{}''\n", config.name);
            assert!(stderr.write(msg.as_bytes()).is_ok());
            os::set_exit_status(1);
            return
        }
    };

    let shared_scene = Arc::new(scene); // Hackish solution for animator

    let scene_time = ::time::get_time().sec;
    println!("Scene loaded at {} ({}s)...", scene_time, scene_time - start_time);

    let renderer = raytracer::Renderer {
        reflect_depth: config.reflect_depth,
        refract_depth: config.refract_depth,
        shadow_samples: config.shadow_samples,
        pixel_samples: config.pixel_samples,
        // Number of tasks to spawn. Will use up max available cores.
        tasks: std::os::num_cpus()
    };

    if config.animating {
        let (animate_from, animate_to) = config.time_slice;

        let animator = raytracer::animator::Animator {
            fps: config.fps,
            animate_from: animate_from,
            animate_to: animate_to,
            starting_frame_number: config.starting_frame_number,
            renderer: renderer
        };

        println!("Animating - tasks: {}, FPS: {}, start: {}s, end:{}s, starting frame: {}",
                 renderer.tasks, animator.fps, animator.animate_from, animator.animate_to,
                 animator.starting_frame_number);
        animator.animate(camera, shared_scene, config.output_file.as_slice());
        let render_time = ::time::get_time().sec;
        println!("Render done at {} ({}s)",
                 render_time, render_time - scene_time);
    } else {
        // Still frame
        println!("Rendering with {} tasks...", renderer.tasks);
        let image_data = renderer.render(camera, shared_scene);
        let render_time = ::time::get_time().sec;
        println!("Render done at {} ({}s)...\nWriting file...",
                 render_time, render_time - scene_time);

        let out_file = format!("{}{}", config.output_file.as_slice(), ".ppm");
        util::export::to_ppm(image_data, out_file.as_slice());
        let export_time = ::time::get_time().sec;

        println!("Write done: {} ({}s). Written to {}\nTotal: {}s",
                 export_time, export_time - render_time,
                 config.output_file.as_slice(), export_time - start_time);
    }
}
<commit_msg>breaking change: obsolete syntax: ..xs -> xs..<commit_after>#![feature(macro_rules)]

extern crate time;
extern crate serialize;

use scene::{Camera, Scene};

use std::io::File;
use std::io;
use std::os;
use std::sync::Arc;
use serialize::json;
use serialize::json::MissingFieldError;

mod geometry;
mod light;
mod material;
mod my_scene;
mod raytracer;
mod scene;
mod util;
mod vec3;
mod mat4;

// Replace this with argparse eventually
struct ProgramArgs {
    config_file: String
}

#[deriving(Decodable, Encodable)]
struct SceneConfig<'a> {
    name: String,
    size: (int, int),
    fov: f64,
    reflect_depth: uint,
    refract_depth: uint,
    shadow_samples: uint,
    pixel_samples: uint,
    output_file: String,
    animating: bool,
    fps: f64,
    time_slice: (f64, f64),
    starting_frame_number: uint
}

fn parse_args(args: Vec<String>) -> Result<ProgramArgs, String>  {
    let (program_name, rest) = match args.as_slice() {
        // I wouldn't expect this in the wild
        [] => fail!("Args do not even include a program name"),
        [ref program_name, rest..] => (
            program_name,
            rest
        )
    };
    match rest.len() {
        0 => Err(format!("Usage: {} scene_config.json", program_name)),
        1 => Ok(ProgramArgs {
            config_file: rest[0].clone()
        }),
        _ => Err(format!("Usage: {} scene_config.json", program_name)),
    }
}

fn get_camera_and_scene(config: &SceneConfig) -> Option<(Camera, Scene)> {
    let scene_name = config.name.clone();
    let (image_width, image_height) = config.size;
    let fov = config.fov;

    // Cameras, scenes created in ./my_scene.rs
    // Scenes with an octree supplied (see my_scene.rs) will use it.
    // Lower the render quality (especially shadow_samples) for complex scenes
    return match scene_name.as_slice() {
        "box" => {
            // Box. Simplest scene with 9 primitives, no octree
            let camera = my_scene::cornell::get_camera(image_width, image_height, fov);
            let scene = my_scene::cornell::get_scene();
            Some((camera, scene))
        },
        "bunny" => {
            // Bunny. Around 300 primitives, 2 lights. Uses octree. Has skybox, textures are
            // in another repository.
            let camera = my_scene::bunny::get_camera(image_width, image_height, fov);
            let scene = my_scene::bunny::get_scene();
            Some((camera, scene))
        },
        "teapot" => {
            // Teapot. Around 2500 polygons. Octree helps a bit. Has skybox.
            let camera = my_scene::teapot::get_teapot_camera(image_width, image_height, fov);
            let scene = my_scene::teapot::get_teapot_scene();
            Some((camera, scene))
        },
        "cow" => {
            // Cow. Around 5000 polygons. Octree helps considerably.
            let camera = my_scene::cow::get_camera(image_width, image_height, fov);
            let scene = my_scene::cow::get_scene();
            Some((camera, scene))
        },
        "lucy" => {
            // Lucy. Around 525814+1 primitives. Octree pretty much required. The model is included
            // separately, in another repository. Has skybox.
            let camera = my_scene::lucy::get_camera(image_width, image_height, fov);
            let scene = my_scene::lucy::get_scene();
            Some((camera, scene))
        },
        "sponza" => {
            // Sponza. Around 28K triangles, but more complex than Lucy. 2 lights.
            let camera = my_scene::sponza::get_camera(image_width, image_height, fov);
            let scene = my_scene::sponza::get_scene();
            Some((camera, scene))
        },
        "sibenik" => {
            // Sibenik, around 70K triangles, no texture work, 3 lights.
            let camera = match config.animating {
                true => my_scene::sibenik::get_animation_camera(image_width, image_height, fov),
                false => my_scene::sibenik::get_camera(image_width, image_height, fov)
            };
            let scene = my_scene::sibenik::get_scene();
            Some((camera, scene))
        },
        "heptoroid-white" => {
            // Heptoroid, 114688 tris, 57302 verts
            let camera = my_scene::heptoroid::get_camera(image_width, image_height, fov);
            let scene = my_scene::heptoroid::get_scene("white");
            Some((camera, scene))
        },
        "heptoroid-shiny" => {
            // Shiny heptoroid, 114688 tris, 57302 verts
            let camera = my_scene::heptoroid::get_camera(image_width, image_height, fov);
            let scene = my_scene::heptoroid::get_scene("shiny");
            Some((camera, scene))
        },
        "heptoroid-refractive" => {
            // Refractive heptoroid, you want to limit your reflect levels (2/3?)
            // and up your refract levels (10/16?) for this
            let camera = my_scene::heptoroid::get_camera(image_width, image_height, fov);
            let scene = my_scene::heptoroid::get_scene("refractive");
            Some((camera, scene))
        },
        "tachikoma" => {
            // Shiny heptoroid, 114688 tris, 57302 verts
            // You can forget about refractions, it's too complex a scene
            let camera = my_scene::tachikoma::get_camera(image_width, image_height, fov);
            let scene = my_scene::tachikoma::get_scene();
            Some((camera, scene))
        },
        "sphere" => {
            // Sphere skybox test scene
            let camera = match config.animating {
                true => my_scene::sphere::get_animation_camera(image_width, image_height, fov),
                false => my_scene::sphere::get_camera(image_width, image_height, fov)
            };
            let scene = my_scene::sphere::get_scene();
            Some((camera, scene))
        },
        "fresnel" => {
            // Fresnel test scene
            let camera = match config.animating {
                true => my_scene::fresnel::get_animation_camera(image_width, image_height, fov),
                false => my_scene::fresnel::get_camera(image_width, image_height, fov)
            };
            let scene = my_scene::fresnel::get_scene();
            Some((camera, scene))
        },
        _ => None
    };
}

fn main() {
    let start_time = ::time::get_time().sec;

    let program_args = match parse_args(os::args()) {
        Ok(program_args) => program_args,
        Err(error_str) => {
            let mut stderr = io::stderr();
            assert!(stderr.write(error_str.append("\n").as_bytes()).is_ok());
            os::set_exit_status(1);
            return
        }
    };
    let config_path = Path::new(program_args.config_file);
    let mut file_handle = match File::open(&config_path) {
        Ok(file) => file,
        Err(err) => {
            let mut stderr = io::stderr();
            assert!(stderr.write(format!("{}", err).append("\n").as_bytes()).is_ok());
            os::set_exit_status(1);
            return
        }
    };
    let json_data = match file_handle.read_to_string() {
        Ok(data) => data,
        Err(err) => {
            let mut stderr = io::stderr();
            assert!(stderr.write(format!("{}", err).append("\n").as_bytes()).is_ok());
            os::set_exit_status(1);
            return
        }
    };

    let config: SceneConfig = match json::decode(json_data.as_slice()) {
        Ok(data) => data,
        Err(err) => {
            let mut stderr = io::stderr();
            let msg = match err {
                MissingFieldError(field_name) => {
                    format!("parse failure, missing field ``{}''\n", field_name)
                },
                _ => {
                    format!("parse failure: {}", err)
                }
            };
            assert!(stderr.write(msg.as_bytes()).is_ok());
            os::set_exit_status(1);
            return
        }
    };

    println!("Job started at {}...\nLoading scene...", start_time);

    let scenepair = get_camera_and_scene(&config);
    let (camera, scene) = match scenepair {
        Some(pair) => pair,
        None => {
            let mut stderr = io::stderr();
            let msg = format!("unknown scene ``{}''\n", config.name);
            assert!(stderr.write(msg.as_bytes()).is_ok());
            os::set_exit_status(1);
            return
        }
    };

    let shared_scene = Arc::new(scene); // Hackish solution for animator

    let scene_time = ::time::get_time().sec;
    println!("Scene loaded at {} ({}s)...", scene_time, scene_time - start_time);

    let renderer = raytracer::Renderer {
        reflect_depth: config.reflect_depth,
        refract_depth: config.refract_depth,
        shadow_samples: config.shadow_samples,
        pixel_samples: config.pixel_samples,
        // Number of tasks to spawn. Will use up max available cores.
        tasks: std::os::num_cpus()
    };

    if config.animating {
        let (animate_from, animate_to) = config.time_slice;

        let animator = raytracer::animator::Animator {
            fps: config.fps,
            animate_from: animate_from,
            animate_to: animate_to,
            starting_frame_number: config.starting_frame_number,
            renderer: renderer
        };

        println!("Animating - tasks: {}, FPS: {}, start: {}s, end:{}s, starting frame: {}",
                 renderer.tasks, animator.fps, animator.animate_from, animator.animate_to,
                 animator.starting_frame_number);
        animator.animate(camera, shared_scene, config.output_file.as_slice());
        let render_time = ::time::get_time().sec;
        println!("Render done at {} ({}s)",
                 render_time, render_time - scene_time);
    } else {
        // Still frame
        println!("Rendering with {} tasks...", renderer.tasks);
        let image_data = renderer.render(camera, shared_scene);
        let render_time = ::time::get_time().sec;
        println!("Render done at {} ({}s)...\nWriting file...",
                 render_time, render_time - scene_time);

        let out_file = format!("{}{}", config.output_file.as_slice(), ".ppm");
        util::export::to_ppm(image_data, out_file.as_slice());
        let export_time = ::time::get_time().sec;

        println!("Write done: {} ({}s). Written to {}\nTotal: {}s",
                 export_time, export_time - render_time,
                 config.output_file.as_slice(), export_time - start_time);
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use std::string::String;
use std::collections::HashMap;
use std::vec::Vec;
use std::fs::{File};
use std::env;
use std::path::{Path};
use std::io::{self, BufReader, BufRead};

use rand::{random, Closed01, Rng};
use rand::distributions::{IndependentSample, Range, Sample, Gamma};

type Bag = HashMap<usize, usize>;

fn load_bags<P: AsRef<Path>>(path: P) -> io::Result<(Vec<usize>, Vec<Bag>)> {
    let mut bags = Vec::new();
    let mut labels = Vec::new();
    let file = try!(File::open(path));
    let file = BufReader::new(file);
    for line in file.lines() {
        let line = line.unwrap();
        let mut iter = line.split_whitespace();
        let label = iter.next().unwrap().parse::<usize>().unwrap();
        let mut bag = Bag::new();
        for elm in iter {
            let mut iter = elm.split(':');
            let index = iter.next().unwrap().parse::<usize>().unwrap();
            let value = iter.next().unwrap().parse::<usize>().unwrap();
            bag.insert(index - 1, value);
        }
        labels.push(label);
        bags.push(bag);
    }
    Ok((labels, bags))
}

fn load_text_vocabulary<P: AsRef<Path>>(path: P) -> io::Result<Vec<String>> {
    let mut vocab = Vec::new();
    let file = try!(File::open(path));
    let file = BufReader::new(file);
    for line in file.lines() {
        let line = line.unwrap();
        vocab.push(line);
    }
    Ok(vocab)
}

#[derive(Clone)]
struct Categorical {
    prop: Vec<f64>,
}

impl Categorical {
    fn new(weights: Vec<f64>) -> Categorical {
        let sum: f64 = weights.iter().sum();
        let prop: Vec<f64> = weights.iter().map(|w| w / sum).collect();
        Categorical {
            prop: prop,
        }
    }
}

impl Sample<usize> for Categorical {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> usize {
        self.ind_sample(rng)
    }
}

impl IndependentSample<usize> for Categorical {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> usize {
        let Closed01(x) = random::<Closed01<f64>>();

        let mut sum = 0.0;
        let mut ret = self.prop.len() - 1;
        for (k, &p) in self.prop.iter().enumerate() {
            sum += p;
            if x <= sum {
                ret = k;
                break;
            }
        }
        ret
    }
}

#[derive(Clone)]
struct Dirichlet {
    alpha: Vec<f64>,
}

impl Dirichlet {
    fn new(alpha: Vec<f64>) -> Dirichlet {
        Dirichlet {
            alpha: alpha,
        }
    }
}

impl Sample<Vec<f64>> for Dirichlet {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Vec<f64> {
        self.ind_sample(rng)
    }
}

impl IndependentSample<Vec<f64>> for Dirichlet {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Vec<f64> {
        let mut sum = 0.0;
        let mut xs = Vec::new();
        for &a in &self.alpha {
            let gamma = Gamma::new(a, 1.0);
            let y = gamma.ind_sample(rng);
            xs.push(y);
            sum += y;
        }
        for x in xs.iter_mut() {
            *x /= sum;
        }
        xs
    }
}

fn lda(num_topics: usize, dataset: Vec<Bag>, alpha: Vec<f64>, beta: Vec<f64>, num_samples: usize) {
    // Initialization
    let mut rng = rand::thread_rng();
    let topics = Range::new(0, num_topics);

    let vocab_size: usize = {
        let mut have_some = false;
        let mut max_index = 0;
        for bag in &dataset {
            for &index in bag.keys() {
                have_some = true;
                if index > max_index {
                    max_index = index;
                }
            }
        }
        if have_some {
            max_index + 1
        }
        else {
            0
        }
    };
    println!("K = {}", num_topics);
    println!("M = {}", &dataset.len());
    println!("V = {}", vocab_size);

    let mut w: Vec<Vec<usize>> = Vec::new();
    let mut z: Vec<Vec<usize>> = Vec::new();
    let mut theta: Vec<Vec<f64>> = Vec::new();
    let mut ndk: Vec<Vec<usize>> = Vec::new();
    for bag in &dataset {
        // w
        let mut w_d = Vec::new();
        for (&index, &count) in bag {
            for _ in 0..count {
                w_d.push(index);
            }
        }
        w.push(w_d);
        // z
        let mut z_d = Vec::new();
        for &count in bag.values() {
            for _ in 0..count {
                z_d.push(0);
            }
        }
        let n_d = z_d.len();
        z.push(z_d);
        // theta
        let mut theta_d = Vec::with_capacity(num_topics);
        for _k in 0..num_topics {
            theta_d.push(1.0 / num_topics as f64);
        }
        theta.push(theta_d);
        // ndk
        let mut ndk_d = Vec::with_capacity(num_topics);
        ndk_d.push(n_d);
        for _k in 1..num_topics {
            ndk_d.push(0);
        }
        ndk.push(ndk_d);
    }
    println!("z = {:?}", z);
    println!("theta = {:?}", theta);
    println!("ndk = {:?}", ndk);

    let mut phi: Vec<Vec<f64>> = Vec::new();
    let mut nkv: Vec<Vec<usize>> = Vec::new();
    // phi
    for _k in 0..num_topics {
        let mut phi_k = Vec::new();
        for _v in 0..vocab_size {
            phi_k.push(1.0 / vocab_size as f64);
        }
        phi.push(phi_k);
    }
    // nkv
    let mut nkv_0 = Vec::new();
    for _v in 0..vocab_size {
        nkv_0.push(0);
    }
    for bag in &dataset {
        for (&index, &count) in bag {
            nkv_0[index] += count;
        }
    }
    nkv.push(nkv_0);
    for _k in 1..num_topics {
        let mut nkv_k = Vec::new();
        for _v in 0..vocab_size {
            nkv_k.push(0);
        }
        nkv.push(nkv_k);
    }
    println!("phi = {:?}", phi);
    println!("nkv = {:?}", nkv);

    // Sampling
    let mut rng = rand::thread_rng();
    for s in 0..num_samples {
        for (d, w_d) in w.iter().enumerate() {
            for (i, &w_di) in w_d.iter().enumerate() {
                let v = w_di;
                // Sample z_di
                let mut weights: Vec<f64> = Vec::new();
                for k in 0..num_topics {
                    weights.push(theta[d][k] * phi[k][v]);
                }
                let cat = Categorical::new(weights);
                let old_z_di = z[d][i];
                let new_z_di = cat.ind_sample(&mut rng);
                z[d][i] = new_z_di;
                // Update ndk and nkv
                ndk[d][old_z_di] -= 1;
                ndk[d][new_z_di] += 1;
                nkv[old_z_di][v] -= 1;
                nkv[new_z_di][v] += 1;
            }
            // Sample theta_d
            let mut alpha_d: Vec<f64> = Vec::new();
            for k in 0..num_topics {
                alpha_d.push(ndk[d][k] as f64 + alpha[k]);
            }
            let dir = Dirichlet::new(alpha_d);
            theta[d] = dir.ind_sample(&mut rng);
        }
        for k in 0..num_topics {
            // Sample phi_k
            let mut beta_k: Vec<f64> = Vec::new();
            for v in 0..vocab_size {
                beta_k.push(nkv[k][v] as f64 + beta[v]);
            }
            let dir = Dirichlet::new(beta_k);
            phi[k] = dir.ind_sample(&mut rng);
        }
        // Evaluate the log-likelihood value for the current parameters
        let mut log_likelihood = 0.0;
        for k in 0..num_topics {
            for v in 0..vocab_size {
                log_likelihood += nkv[k][v] as f64 * f64::ln(phi[k][v]);
            }
        }
        println!("log_likelihood = {}", log_likelihood);
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let (labels, dataset) = load_bags(&args[1]).unwrap();
    let vocab: Option<Vec<String>> = if args.len() < 3 {
        None
    }
    else {
        Some(load_text_vocabulary(&args[2]).unwrap())
    };
    println!("{:?}", labels);
    println!("{:?}", dataset);
    println!("{:?}", vocab);

    lda(3, dataset, vec![1.0, 1.0, 1.0], vec![1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], 100);
}
<commit_msg>Pass alpha and beta of correct lengths<commit_after>extern crate rand;

use std::string::String;
use std::collections::HashMap;
use std::vec::Vec;
use std::fs::{File};
use std::env;
use std::path::{Path};
use std::io::{self, BufReader, BufRead};
use std::iter;

use rand::{random, Closed01, Rng};
use rand::distributions::{IndependentSample, Range, Sample, Gamma};

type Bag = HashMap<usize, usize>;

fn load_bags<P: AsRef<Path>>(path: P) -> io::Result<(Vec<usize>, Vec<Bag>)> {
    let mut bags = Vec::new();
    let mut labels = Vec::new();
    let file = try!(File::open(path));
    let file = BufReader::new(file);
    for line in file.lines() {
        let line = line.unwrap();
        let mut iter = line.split_whitespace();
        let label = iter.next().unwrap().parse::<usize>().unwrap();
        let mut bag = Bag::new();
        for elm in iter {
            let mut iter = elm.split(':');
            let index = iter.next().unwrap().parse::<usize>().unwrap();
            let value = iter.next().unwrap().parse::<usize>().unwrap();
            bag.insert(index - 1, value);
        }
        labels.push(label);
        bags.push(bag);
    }
    Ok((labels, bags))
}

fn load_text_vocabulary<P: AsRef<Path>>(path: P) -> io::Result<Vec<String>> {
    let mut vocab = Vec::new();
    let file = try!(File::open(path));
    let file = BufReader::new(file);
    for line in file.lines() {
        let line = line.unwrap();
        vocab.push(line);
    }
    Ok(vocab)
}

#[derive(Clone)]
struct Categorical {
    prop: Vec<f64>,
}

impl Categorical {
    fn new(weights: Vec<f64>) -> Categorical {
        let sum: f64 = weights.iter().sum();
        let prop: Vec<f64> = weights.iter().map(|w| w / sum).collect();
        Categorical {
            prop: prop,
        }
    }
}

impl Sample<usize> for Categorical {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> usize {
        self.ind_sample(rng)
    }
}

impl IndependentSample<usize> for Categorical {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> usize {
        let Closed01(x) = random::<Closed01<f64>>();

        let mut sum = 0.0;
        let mut ret = self.prop.len() - 1;
        for (k, &p) in self.prop.iter().enumerate() {
            sum += p;
            if x <= sum {
                ret = k;
                break;
            }
        }
        ret
    }
}

#[derive(Clone)]
struct Dirichlet {
    alpha: Vec<f64>,
}

impl Dirichlet {
    fn new(alpha: Vec<f64>) -> Dirichlet {
        Dirichlet {
            alpha: alpha,
        }
    }
}

impl Sample<Vec<f64>> for Dirichlet {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Vec<f64> {
        self.ind_sample(rng)
    }
}

impl IndependentSample<Vec<f64>> for Dirichlet {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Vec<f64> {
        let mut sum = 0.0;
        let mut xs = Vec::new();
        for &a in &self.alpha {
            let gamma = Gamma::new(a, 1.0);
            let y = gamma.ind_sample(rng);
            xs.push(y);
            sum += y;
        }
        for x in xs.iter_mut() {
            *x /= sum;
        }
        xs
    }
}

fn lda(num_topics: usize, dataset: Vec<Bag>, alpha: Vec<f64>, beta: Vec<f64>, num_samples: usize) {
    // Initialization
    let mut rng = rand::thread_rng();
    let topics = Range::new(0, num_topics);

    let vocab_size: usize = {
        let mut have_some = false;
        let mut max_index = 0;
        for bag in &dataset {
            for &index in bag.keys() {
                have_some = true;
                if index > max_index {
                    max_index = index;
                }
            }
        }
        if have_some {
            max_index + 1
        }
        else {
            0
        }
    };
    println!("K = {}", num_topics);
    println!("M = {}", &dataset.len());
    println!("V = {}", vocab_size);

    let mut w: Vec<Vec<usize>> = Vec::new();
    let mut z: Vec<Vec<usize>> = Vec::new();
    let mut theta: Vec<Vec<f64>> = Vec::new();
    let mut ndk: Vec<Vec<usize>> = Vec::new();
    for bag in &dataset {
        // w
        let mut w_d = Vec::new();
        for (&index, &count) in bag {
            for _ in 0..count {
                w_d.push(index);
            }
        }
        w.push(w_d);
        // z
        let mut z_d = Vec::new();
        for &count in bag.values() {
            for _ in 0..count {
                z_d.push(0);
            }
        }
        let n_d = z_d.len();
        z.push(z_d);
        // theta
        let mut theta_d = Vec::with_capacity(num_topics);
        for _k in 0..num_topics {
            theta_d.push(1.0 / num_topics as f64);
        }
        theta.push(theta_d);
        // ndk
        let mut ndk_d = Vec::with_capacity(num_topics);
        ndk_d.push(n_d);
        for _k in 1..num_topics {
            ndk_d.push(0);
        }
        ndk.push(ndk_d);
    }
    println!("z = {:?}", z);
    println!("theta = {:?}", theta);
    println!("ndk = {:?}", ndk);

    let mut phi: Vec<Vec<f64>> = Vec::new();
    let mut nkv: Vec<Vec<usize>> = Vec::new();
    // phi
    for _k in 0..num_topics {
        let mut phi_k = Vec::new();
        for _v in 0..vocab_size {
            phi_k.push(1.0 / vocab_size as f64);
        }
        phi.push(phi_k);
    }
    // nkv
    let mut nkv_0 = Vec::new();
    for _v in 0..vocab_size {
        nkv_0.push(0);
    }
    for bag in &dataset {
        for (&index, &count) in bag {
            nkv_0[index] += count;
        }
    }
    nkv.push(nkv_0);
    for _k in 1..num_topics {
        let mut nkv_k = Vec::new();
        for _v in 0..vocab_size {
            nkv_k.push(0);
        }
        nkv.push(nkv_k);
    }
    println!("phi = {:?}", phi);
    println!("nkv = {:?}", nkv);

    // Sampling
    let mut rng = rand::thread_rng();
    for s in 0..num_samples {
        for (d, w_d) in w.iter().enumerate() {
            for (i, &w_di) in w_d.iter().enumerate() {
                let v = w_di;
                // Sample z_di
                let mut weights: Vec<f64> = Vec::new();
                for k in 0..num_topics {
                    weights.push(theta[d][k] * phi[k][v]);
                }
                let cat = Categorical::new(weights);
                let old_z_di = z[d][i];
                let new_z_di = cat.ind_sample(&mut rng);
                z[d][i] = new_z_di;
                // Update ndk and nkv
                ndk[d][old_z_di] -= 1;
                ndk[d][new_z_di] += 1;
                nkv[old_z_di][v] -= 1;
                nkv[new_z_di][v] += 1;
            }
            // Sample theta_d
            let mut alpha_d: Vec<f64> = Vec::new();
            for k in 0..num_topics {
                alpha_d.push(ndk[d][k] as f64 + alpha[k]);
            }
            let dir = Dirichlet::new(alpha_d);
            theta[d] = dir.ind_sample(&mut rng);
        }
        for k in 0..num_topics {
            // Sample phi_k
            let mut beta_k: Vec<f64> = Vec::new();
            for v in 0..vocab_size {
                beta_k.push(nkv[k][v] as f64 + beta[v]);
            }
            let dir = Dirichlet::new(beta_k);
            phi[k] = dir.ind_sample(&mut rng);
        }
        // Evaluate the log-likelihood value for the current parameters
        let mut log_likelihood = 0.0;
        for k in 0..num_topics {
            for v in 0..vocab_size {
                log_likelihood += nkv[k][v] as f64 * f64::ln(phi[k][v]);
            }
        }
        println!("log_likelihood = {}", log_likelihood);
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let (labels, dataset) = load_bags(&args[1]).unwrap();
    let vocab: Option<Vec<String>> = if args.len() < 3 {
        None
    }
    else {
        Some(load_text_vocabulary(&args[2]).unwrap())
    };
    println!("{:?}", labels);
    println!("{:?}", dataset);
    println!("{:?}", vocab);

    let num_topics = 3;
    let alpha: Vec<f64> = iter::repeat(1.0).take(num_topics).collect();
    let beta: Vec<f64> = iter::repeat(1.0).take(vocab.unwrap().len()).collect();

    lda(num_topics, dataset, alpha, beta, 100000);
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 The Noise-rs Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT
// or http://opensource.org/licenses/MIT>, at your option. All files in the
// project carrying such notice may not be copied, modified, or distributed
// except according to those terms.

//! An ultra-light private math library to make our short lives easier as we
//! implement super-complex noise stuff.

use std::ops::{Add, Mul, Sub};

/// Cast a numeric type without having to unwrap - we don't expect any overflow
/// errors...
#[inline]
pub fn cast<T, U: From<T>>(x: T) -> U {
    From::from(x)
}

/// A 2-dimensional point. This is a fixed sized array, so should be compatible
/// with most linear algebra libraries.
pub type Point2<T> = [T; 2];

/// A 3-dimensional point. This is a fixed sized array, so should be compatible
/// with most linear algebra libraries.
pub type Point3<T> = [T; 3];

/// A 4-dimensional point. This is a fixed sized array, so should be compatible
/// with most linear algebra libraries.
pub type Point4<T> = [T; 4];

/// A 2-dimensional vector, for internal use.
pub type Vector2<T> = [T; 2];
/// A 3-dimensional vector, for internal use.
pub type Vector3<T> = [T; 3];
/// A 4-dimensional vector, for internal use.
pub type Vector4<T> = [T; 4];

#[inline]
pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
    assert!(max >= min);

    let mut x = input;
    if x < min {
        x = min;
    }
    if x > max {
        x = max;
    }
    x
}

#[inline]
pub fn map2<T, U, F>(a: Vector2<T>, f: F) -> Vector2<U>
where
    T: Copy,
    F: Fn(T) -> U,
{
    let (ax, ay) = (a[0], a[1]);
    [f(ax), f(ay)]
}

#[inline]
pub fn map3<T, U, F>(a: Vector3<T>, f: F) -> Vector3<U>
where
    T: Copy,
    F: Fn(T) -> U,
{
    let (ax, ay, az) = (a[0], a[1], a[2]);
    [f(ax), f(ay), f(az)]
}

#[inline]
pub fn map4<T, U, F>(a: Vector4<T>, f: F) -> Vector4<U>
where
    T: Copy,
    F: Fn(T) -> U,
{
    let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
    [f(ax), f(ay), f(az), f(aw)]
}

#[inline]
pub fn zip_with2<T, U, V, F>(a: Vector2<T>, b: Vector2<U>, f: F) -> Vector2<V>
where
    T: Copy,
    U: Copy,
    F: Fn(T, U) -> V,
{
    let (ax, ay) = (a[0], a[1]);
    let (bx, by) = (b[0], b[1]);
    [f(ax, bx), f(ay, by)]
}

#[inline]
pub fn zip_with3<T, U, V, F>(a: Vector3<T>, b: Vector3<U>, f: F) -> Vector3<V>
where
    T: Copy,
    U: Copy,
    F: Fn(T, U) -> V,
{
    let (ax, ay, az) = (a[0], a[1], a[2]);
    let (bx, by, bz) = (b[0], b[1], b[2]);
    [f(ax, bx), f(ay, by), f(az, bz)]
}

#[inline]
pub fn zip_with4<T, U, V, F>(a: Vector4<T>, b: Vector4<U>, f: F) -> Vector4<V>
where
    T: Copy,
    U: Copy,
    F: Fn(T, U) -> V,
{
    let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
    let (bx, by, bz, bw) = (b[0], b[1], b[2], b[3]);
    [f(ax, bx), f(ay, by), f(az, bz), f(aw, bw)]
}

#[inline]
pub fn fold2<T, F>(a: Vector2<T>, f: F) -> T
where
    T: Copy,
    F: Fn(T, T) -> T,
{
    let (ax, ay) = (a[0], a[1]);
    f(ax, ay)
}

#[inline]
pub fn fold3<T, F>(a: Vector3<T>, f: F) -> T
where
    T: Copy,
    F: Fn(T, T) -> T,
{
    let (ax, ay, az) = (a[0], a[1], a[2]);
    f(f(ax, ay), az)
}

#[inline]
pub fn fold4<T, F>(a: Vector4<T>, f: F) -> T
where
    T: Copy,
    F: Fn(T, T) -> T,
{
    let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
    f(f(f(ax, ay), az), aw)
}

#[inline]
pub fn add2<T>(a: Point2<T>, b: Vector2<T>) -> Point2<T>
where
    T: Copy + Add<T, Output = T>,
{
    zip_with2(a, b, Add::add)
}

#[inline]
pub fn add3<T>(a: Point3<T>, b: Vector3<T>) -> Point3<T>
where
    T: Copy + Add<T, Output = T>,
{
    zip_with3(a, b, Add::add)
}

#[inline]
pub fn add4<T>(a: Point4<T>, b: Vector4<T>) -> Point4<T>
where
    T: Copy + Add<T, Output = T>,
{
    zip_with4(a, b, Add::add)
}

#[inline]
pub fn sub2<T>(a: Point2<T>, b: Point2<T>) -> Vector2<T>
where
    T: Copy + Sub<T, Output = T>,
{
    zip_with2(a, b, Sub::sub)
}

#[inline]
pub fn sub3<T>(a: Point3<T>, b: Point3<T>) -> Vector3<T>
where
    T: Copy + Sub<T, Output = T>,
{
    zip_with3(a, b, Sub::sub)
}

#[inline]
pub fn sub4<T>(a: Point4<T>, b: Point4<T>) -> Vector4<T>
where
    T: Copy + Sub<T, Output = T>,
{
    zip_with4(a, b, Sub::sub)
}

#[inline]
pub fn mul2<T>(a: Vector2<T>, b: T) -> Vector2<T>
where
    T: Copy + Mul<T, Output = T>,
{
    zip_with2(a, const2(b), Mul::mul)
}

#[inline]
pub fn mul3<T>(a: Vector3<T>, b: T) -> Vector3<T>
where
    T: Copy + Mul<T, Output = T>,
{
    zip_with3(a, const3(b), Mul::mul)
}

#[inline]
pub fn mul4<T>(a: Vector4<T>, b: T) -> Vector4<T>
where
    T: Copy + Mul<T, Output = T>,
{
    zip_with4(a, const4(b), Mul::mul)
}

#[inline]
pub fn dot2(a: Vector2<f64>, b: Vector2<f64>) -> f64 {
    fold2(zip_with2(a, b, Mul::mul), Add::add)
}

#[inline]
pub fn dot3(a: Vector3<f64>, b: Vector3<f64>) -> f64 {
    fold3(zip_with3(a, b, Mul::mul), Add::add)
}

#[inline]
pub fn dot4(a: Vector4<f64>, b: Vector4<f64>) -> f64 {
    fold4(zip_with4(a, b, Mul::mul), Add::add)
}

#[inline]
pub fn const2<T: Copy>(x: T) -> Vector2<T> {
    [x, x]
}

#[inline]
pub fn const3<T: Copy>(x: T) -> Vector3<T> {
    [x, x, x]
}

#[inline]
pub fn const4<T: Copy>(x: T) -> Vector4<T> {
    [x, x, x, x]
}

#[inline]
pub fn one2<T: Copy + From<i8>>() -> Vector2<T> {
    cast2(const2(1))
}

#[inline]
pub fn one3<T: Copy + From<i8>>() -> Vector3<T> {
    cast3(const3(1))
}

#[inline]
pub fn one4<T: Copy + From<i8>>() -> Vector4<T> {
    cast4(const4(1))
}

#[inline]
pub fn cast2<T, U>(x: Point2<T>) -> Point2<U>
where
    T: Copy,
    U: Copy + From<T>,
{
    map2(x, cast)
}

#[inline]
pub fn cast3<T, U>(x: Point3<T>) -> Point3<U>
where
    T: Copy,
    U: Copy + From<T>,
{
    map3(x, cast)
}

#[inline]
pub fn cast4<T, U>(x: Point4<T>) -> Point4<U>
where
    T: Copy,
    U: Copy + From<T>,
{
    map4(x, cast)
}

// f64 doesn't implement From<isize>
#[inline]
pub fn to_f642(x: Point2<isize>) -> Point2<f64> {
    [x[0] as f64, x[1] as f64]
}

#[inline]
pub fn to_f643(x: Point3<isize>) -> Point3<f64> {
    [x[0] as f64, x[1] as f64, x[2] as f64]
}

#[inline]
pub fn to_f644(x: Point4<isize>) -> Point4<f64> {
    [x[0] as f64, x[1] as f64, x[2] as f64, x[3] as f64]
}

// isize doesn't implement From<f64>
#[inline]
pub fn to_isize2(x: Point2<f64>) -> Point2<isize> {
    [x[0] as isize, x[1] as isize]
}

#[cfg(not(target_os = "emscripten"))]
#[inline]
pub fn scale_shift(value: f64, n: f64) -> f64 {
    value.abs().mul_add(cast(n), -1.0_f64)
}

#[cfg(target_os = "emscripten")]
#[inline]
pub fn scale_shift(value: f64, n: f64) -> f64 {
    (value.abs() * cast(n)) + -1.0_f64
}

#[inline]
pub fn to_isize3(x: Point3<f64>) -> Point3<isize> {
    [x[0] as isize, x[1] as isize, x[2] as isize]
}

#[inline]
pub fn to_isize4(x: Point4<f64>) -> Point4<isize> {
    [
        x[0] as isize,
        x[1] as isize,
        x[2] as isize,
        x[3] as isize,
    ]
}

pub mod interp {
    /// Performs linear interploation between two values.
    #[cfg(not(target_os = "emscripten"))]
    #[inline]
    pub fn linear(a: f64, b: f64, x: f64) -> f64 {
        x.mul_add((b - a), a)
    }

    /// Performs linear interploation between two values.
    #[cfg(target_os = "emscripten")]
    #[inline]
    pub fn linear<T: Float>(a: T, b: T, x: T) -> T {
        (x * (b - a)) + a
    }

    /// Performs cubic interpolation between two values bound between two other
    /// values.
    ///
    /// - n0 - The value before the first value.
    /// - n1 - The first value.
    /// - n2 - The second value.
    /// - n3 - The value after the second value.
    /// - x - The alpha value.
    ///
    /// The alpha value should range from 0.0 to 1.0. If the alpha value is
    /// 0.0, this function returns _n1_. If the alpha value is 1.0, this
    /// function returns _n2_.
    #[inline]
    pub fn cubic(n0: f64, n1: f64, n2: f64, n3: f64, x: f64) -> f64 {
        let p = (n3 - n2) - (n0 - n1);
        let q = (n0 - n1) - p;
        let r = n2 - n0;
        let s = n1;
        p * x * x * x + q * x * x + r * x + s
    }

    /// Maps a value onto a cubic S-curve.
    #[inline]
    pub fn s_curve3(x: f64) -> f64 {
        x * x * (3.0 - (x * 2.0))
    }

    /// Maps a value onto a quintic S-curve.
    #[inline]
    pub fn s_curve5(x: f64) -> f64 {
        x * x * x * (x * (x * 6.0 - 15.0 + 10.0))
    }
}
<commit_msg>Removed remnants of `num_traits` crate<commit_after>// Copyright (c) 2017 The Noise-rs Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT
// or http://opensource.org/licenses/MIT>, at your option. All files in the
// project carrying such notice may not be copied, modified, or distributed
// except according to those terms.

//! An ultra-light private math library to make our short lives easier as we
//! implement super-complex noise stuff.

use std::ops::{Add, Mul, Sub};

/// Cast a numeric type without having to unwrap - we don't expect any overflow
/// errors...
#[inline]
pub fn cast<T, U: From<T>>(x: T) -> U {
    From::from(x)
}

/// A 2-dimensional point. This is a fixed sized array, so should be compatible
/// with most linear algebra libraries.
pub type Point2<T> = [T; 2];

/// A 3-dimensional point. This is a fixed sized array, so should be compatible
/// with most linear algebra libraries.
pub type Point3<T> = [T; 3];

/// A 4-dimensional point. This is a fixed sized array, so should be compatible
/// with most linear algebra libraries.
pub type Point4<T> = [T; 4];

/// A 2-dimensional vector, for internal use.
pub type Vector2<T> = [T; 2];
/// A 3-dimensional vector, for internal use.
pub type Vector3<T> = [T; 3];
/// A 4-dimensional vector, for internal use.
pub type Vector4<T> = [T; 4];

#[inline]
pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
    assert!(max >= min);

    let mut x = input;
    if x < min {
        x = min;
    }
    if x > max {
        x = max;
    }
    x
}

#[inline]
pub fn map2<T, U, F>(a: Vector2<T>, f: F) -> Vector2<U>
where
    T: Copy,
    F: Fn(T) -> U,
{
    let (ax, ay) = (a[0], a[1]);
    [f(ax), f(ay)]
}

#[inline]
pub fn map3<T, U, F>(a: Vector3<T>, f: F) -> Vector3<U>
where
    T: Copy,
    F: Fn(T) -> U,
{
    let (ax, ay, az) = (a[0], a[1], a[2]);
    [f(ax), f(ay), f(az)]
}

#[inline]
pub fn map4<T, U, F>(a: Vector4<T>, f: F) -> Vector4<U>
where
    T: Copy,
    F: Fn(T) -> U,
{
    let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
    [f(ax), f(ay), f(az), f(aw)]
}

#[inline]
pub fn zip_with2<T, U, V, F>(a: Vector2<T>, b: Vector2<U>, f: F) -> Vector2<V>
where
    T: Copy,
    U: Copy,
    F: Fn(T, U) -> V,
{
    let (ax, ay) = (a[0], a[1]);
    let (bx, by) = (b[0], b[1]);
    [f(ax, bx), f(ay, by)]
}

#[inline]
pub fn zip_with3<T, U, V, F>(a: Vector3<T>, b: Vector3<U>, f: F) -> Vector3<V>
where
    T: Copy,
    U: Copy,
    F: Fn(T, U) -> V,
{
    let (ax, ay, az) = (a[0], a[1], a[2]);
    let (bx, by, bz) = (b[0], b[1], b[2]);
    [f(ax, bx), f(ay, by), f(az, bz)]
}

#[inline]
pub fn zip_with4<T, U, V, F>(a: Vector4<T>, b: Vector4<U>, f: F) -> Vector4<V>
where
    T: Copy,
    U: Copy,
    F: Fn(T, U) -> V,
{
    let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
    let (bx, by, bz, bw) = (b[0], b[1], b[2], b[3]);
    [f(ax, bx), f(ay, by), f(az, bz), f(aw, bw)]
}

#[inline]
pub fn fold2<T, F>(a: Vector2<T>, f: F) -> T
where
    T: Copy,
    F: Fn(T, T) -> T,
{
    let (ax, ay) = (a[0], a[1]);
    f(ax, ay)
}

#[inline]
pub fn fold3<T, F>(a: Vector3<T>, f: F) -> T
where
    T: Copy,
    F: Fn(T, T) -> T,
{
    let (ax, ay, az) = (a[0], a[1], a[2]);
    f(f(ax, ay), az)
}

#[inline]
pub fn fold4<T, F>(a: Vector4<T>, f: F) -> T
where
    T: Copy,
    F: Fn(T, T) -> T,
{
    let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
    f(f(f(ax, ay), az), aw)
}

#[inline]
pub fn add2<T>(a: Point2<T>, b: Vector2<T>) -> Point2<T>
where
    T: Copy + Add<T, Output = T>,
{
    zip_with2(a, b, Add::add)
}

#[inline]
pub fn add3<T>(a: Point3<T>, b: Vector3<T>) -> Point3<T>
where
    T: Copy + Add<T, Output = T>,
{
    zip_with3(a, b, Add::add)
}

#[inline]
pub fn add4<T>(a: Point4<T>, b: Vector4<T>) -> Point4<T>
where
    T: Copy + Add<T, Output = T>,
{
    zip_with4(a, b, Add::add)
}

#[inline]
pub fn sub2<T>(a: Point2<T>, b: Point2<T>) -> Vector2<T>
where
    T: Copy + Sub<T, Output = T>,
{
    zip_with2(a, b, Sub::sub)
}

#[inline]
pub fn sub3<T>(a: Point3<T>, b: Point3<T>) -> Vector3<T>
where
    T: Copy + Sub<T, Output = T>,
{
    zip_with3(a, b, Sub::sub)
}

#[inline]
pub fn sub4<T>(a: Point4<T>, b: Point4<T>) -> Vector4<T>
where
    T: Copy + Sub<T, Output = T>,
{
    zip_with4(a, b, Sub::sub)
}

#[inline]
pub fn mul2<T>(a: Vector2<T>, b: T) -> Vector2<T>
where
    T: Copy + Mul<T, Output = T>,
{
    zip_with2(a, const2(b), Mul::mul)
}

#[inline]
pub fn mul3<T>(a: Vector3<T>, b: T) -> Vector3<T>
where
    T: Copy + Mul<T, Output = T>,
{
    zip_with3(a, const3(b), Mul::mul)
}

#[inline]
pub fn mul4<T>(a: Vector4<T>, b: T) -> Vector4<T>
where
    T: Copy + Mul<T, Output = T>,
{
    zip_with4(a, const4(b), Mul::mul)
}

#[inline]
pub fn dot2(a: Vector2<f64>, b: Vector2<f64>) -> f64 {
    fold2(zip_with2(a, b, Mul::mul), Add::add)
}

#[inline]
pub fn dot3(a: Vector3<f64>, b: Vector3<f64>) -> f64 {
    fold3(zip_with3(a, b, Mul::mul), Add::add)
}

#[inline]
pub fn dot4(a: Vector4<f64>, b: Vector4<f64>) -> f64 {
    fold4(zip_with4(a, b, Mul::mul), Add::add)
}

#[inline]
pub fn const2<T: Copy>(x: T) -> Vector2<T> {
    [x, x]
}

#[inline]
pub fn const3<T: Copy>(x: T) -> Vector3<T> {
    [x, x, x]
}

#[inline]
pub fn const4<T: Copy>(x: T) -> Vector4<T> {
    [x, x, x, x]
}

#[inline]
pub fn one2<T: Copy + From<i8>>() -> Vector2<T> {
    cast2(const2(1))
}

#[inline]
pub fn one3<T: Copy + From<i8>>() -> Vector3<T> {
    cast3(const3(1))
}

#[inline]
pub fn one4<T: Copy + From<i8>>() -> Vector4<T> {
    cast4(const4(1))
}

#[inline]
pub fn cast2<T, U>(x: Point2<T>) -> Point2<U>
where
    T: Copy,
    U: Copy + From<T>,
{
    map2(x, cast)
}

#[inline]
pub fn cast3<T, U>(x: Point3<T>) -> Point3<U>
where
    T: Copy,
    U: Copy + From<T>,
{
    map3(x, cast)
}

#[inline]
pub fn cast4<T, U>(x: Point4<T>) -> Point4<U>
where
    T: Copy,
    U: Copy + From<T>,
{
    map4(x, cast)
}

// f64 doesn't implement From<isize>
#[inline]
pub fn to_f642(x: Point2<isize>) -> Point2<f64> {
    [x[0] as f64, x[1] as f64]
}

#[inline]
pub fn to_f643(x: Point3<isize>) -> Point3<f64> {
    [x[0] as f64, x[1] as f64, x[2] as f64]
}

#[inline]
pub fn to_f644(x: Point4<isize>) -> Point4<f64> {
    [x[0] as f64, x[1] as f64, x[2] as f64, x[3] as f64]
}

// isize doesn't implement From<f64>
#[inline]
pub fn to_isize2(x: Point2<f64>) -> Point2<isize> {
    [x[0] as isize, x[1] as isize]
}

#[cfg(not(target_os = "emscripten"))]
#[inline]
pub fn scale_shift(value: f64, n: f64) -> f64 {
    value.abs().mul_add(n, -1.0_f64)
}

#[cfg(target_os = "emscripten")]
#[inline]
pub fn scale_shift(value: f64, n: f64) -> f64 {
    (value.abs() * n) + -1.0_f64
}

#[inline]
pub fn to_isize3(x: Point3<f64>) -> Point3<isize> {
    [x[0] as isize, x[1] as isize, x[2] as isize]
}

#[inline]
pub fn to_isize4(x: Point4<f64>) -> Point4<isize> {
    [
        x[0] as isize,
        x[1] as isize,
        x[2] as isize,
        x[3] as isize,
    ]
}

pub mod interp {
    /// Performs linear interploation between two values.
    #[cfg(not(target_os = "emscripten"))]
    #[inline]
    pub fn linear(a: f64, b: f64, x: f64) -> f64 {
        x.mul_add((b - a), a)
    }

    /// Performs linear interploation between two values.
    #[cfg(target_os = "emscripten")]
    #[inline]
    pub fn linear(a: f64, b: f64, x: f64) -> f64 {
        (x * (b - a)) + a
    }

    /// Performs cubic interpolation between two values bound between two other
    /// values.
    ///
    /// - n0 - The value before the first value.
    /// - n1 - The first value.
    /// - n2 - The second value.
    /// - n3 - The value after the second value.
    /// - x - The alpha value.
    ///
    /// The alpha value should range from 0.0 to 1.0. If the alpha value is
    /// 0.0, this function returns _n1_. If the alpha value is 1.0, this
    /// function returns _n2_.
    #[inline]
    pub fn cubic(n0: f64, n1: f64, n2: f64, n3: f64, x: f64) -> f64 {
        let p = (n3 - n2) - (n0 - n1);
        let q = (n0 - n1) - p;
        let r = n2 - n0;
        let s = n1;
        p * x * x * x + q * x * x + r * x + s
    }

    /// Maps a value onto a cubic S-curve.
    #[inline]
    pub fn s_curve3(x: f64) -> f64 {
        x * x * (3.0 - (x * 2.0))
    }

    /// Maps a value onto a quintic S-curve.
    #[inline]
    pub fn s_curve5(x: f64) -> f64 {
        x * x * x * (x * (x * 6.0 - 15.0 + 10.0))
    }
}
<|endoftext|>