<commit_before>/// Exports the `Term` type which is a high-level API for the Grid
use std::sync::Arc;

use ansi::{self, Attr, DebugHandler};
use grid::{self, Grid, CellFlags};
use tty;
use ::Rgb;

/// tomorrow night bright
///
/// because contrast
pub static COLORS: &'static [Rgb] = &[
    Rgb {r: 0x00, g: 0x00, b: 0x00}, // Black
    Rgb {r: 0xd5, g: 0x4e, b: 0x53}, // Red
    Rgb {r: 0xb9, g: 0xca, b: 0x4a}, // Green
    Rgb {r: 0xe6, g: 0xc5, b: 0x47}, // Yellow
    Rgb {r: 0x7a, g: 0xa6, b: 0xda}, // Blue
    Rgb {r: 0xc3, g: 0x97, b: 0xd8}, // Magenta
    Rgb {r: 0x70, g: 0xc0, b: 0xba}, // Cyan
    Rgb {r: 0x42, g: 0x42, b: 0x42}, // White
    Rgb {r: 0x66, g: 0x66, b: 0x66}, // Bright black
    Rgb {r: 0xff, g: 0x33, b: 0x34}, // Bright red
    Rgb {r: 0x9e, g: 0xc4, b: 0x00}, // Bright green
    Rgb {r: 0xe7, g: 0xc5, b: 0x47}, // Bright yellow
    Rgb {r: 0x7a, g: 0xa6, b: 0xda}, // Bright blue
    Rgb {r: 0xb7, g: 0x7e, b: 0xe0}, // Bright magenta
    Rgb {r: 0x54, g: 0xce, b: 0xd6}, // Bright cyan
    Rgb {r: 0x2a, g: 0x2a, b: 0x2a}, // Bright white
];

pub const CURSOR_SHAPE: char = '█';

pub const DEFAULT_FG: Rgb = Rgb { r: 0xea, g: 0xea, b: 0xea};
pub const DEFAULT_BG: Rgb = Rgb { r: 0, g: 0, b: 0};
pub const TAB_SPACES: usize = 8;

/// State for cursor
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Cursor {
    pub x: u16,
    pub y: u16,
}

impl Default for Cursor {
    fn default() -> Cursor {
        Cursor { x: 0, y: 0 }
    }
}

impl Cursor {
    pub fn goto(&mut self, x: u16, y: u16) {
        self.x = x;
        self.y = y;
    }

    pub fn advance(&mut self, rows: i64, cols: i64) {
        self.x = (self.x as i64 + cols) as u16;
        self.y = (self.y as i64 + rows) as u16;
    }
}

struct Mover<'a> {
    cursor: &'a mut Cursor,
}

pub struct Term {
    /// The grid
    grid: Grid,

    /// Alternate grid
    alt_grid: Grid,

    /// Alt is active
    alt: bool,

    /// Reference to the underlying tty
    tty: tty::Tty,

    /// The cursor
    cursor: Cursor,

    /// Alt cursor
    alt_cursor: Cursor,

    /// Active foreground color
    fg: Rgb,

    /// Active background color
    bg: Rgb,

    /// Tabstops
    tabs: Vec<bool>,

    /// Cell attributes
    attr: grid::CellFlags,
}

impl Term {
    pub fn new(tty: tty::Tty, grid: Grid) -> Term {

        let mut tabs = (0..grid.num_cols()).map(|i| i % TAB_SPACES == 0)
                                       .collect::<Vec<bool>>();
        tabs[0] = false;

        let alt = grid.clone();

        Term {
            grid: grid,
            alt_grid: alt,
            alt: false,
            cursor: Cursor::default(),
            alt_cursor: Cursor::default(),
            fg: DEFAULT_FG,
            bg: DEFAULT_BG,
            tty: tty,
            tabs: tabs,
            attr: CellFlags::empty(),
        }
    }

    pub fn grid(&self) -> &Grid {
        &self.grid
    }

    pub fn swap_alt(&mut self) {
        self.alt = !self.alt;
        ::std::mem::swap(&mut self.grid, &mut self.alt_grid);
        ::std::mem::swap(&mut self.cursor, &mut self.alt_cursor);

        if self.alt {
            self.grid.clear();
        }
    }

    pub fn resize(&mut self) {
        unimplemented!();
    }

    #[inline]
    pub fn cursor_x(&self) -> u16 {
        self.cursor.x
    }

    #[inline]
    pub fn cursor_y(&self) -> u16 {
        self.cursor.y
    }

    #[inline]
    pub fn cursor(&self) -> Cursor {
        self.cursor
    }

    /// Set character in current cursor position
    fn set_char(&mut self, c: char) {
        if self.cursor.x == self.grid.num_cols() as u16 {
            self.cursor.y += 1;
            self.cursor.x = 0;
        }

        let cell = &mut self.grid[self.cursor];
        cell.c = c;
        cell.fg = self.fg;
        cell.bg = self.bg;
        cell.flags = self.attr;
    }

    /// Advance to next line
    fn newline_c(&mut self, count: u16) {
        // TODO handle scroll
        self.cursor.x = 0;
        self.cursor.y += 1;
    }
}

impl ansi::Handler for Term {
    /// A character to be displayed
    #[inline]
    fn input(&mut self, c: char) {
        self.set_char(c);
        self.cursor.x += 1;
    }

    fn goto(&mut self, x: i64, y: i64) {
        println!("goto: x={}, y={}", x, y);
        self.cursor.goto(x as u16, y as u16);
    }
    fn goto_row(&mut self, y: i64) {
        println!("goto_row: {}", y);
        let x = self.cursor_x();
        self.cursor.goto(x, y as u16);
    }
    fn goto_col(&mut self, x: i64) {
        println!("goto_col: {}", x);
        let y = self.cursor_y();
        self.cursor.goto(x as u16, y);
    }

    fn insert_blank(&mut self, num: i64) { println!("insert_blank: {}", num); }

    fn move_up(&mut self, rows: i64) {
        println!("move_up: {}", rows);
        self.cursor.advance(-rows, 0);
    }

    fn move_down(&mut self, rows: i64) {
        println!("move_down: {}", rows);
        self.cursor.advance(rows, 0);
    }

    fn move_forward(&mut self, cols: i64) {
        println!("move_forward: {}", cols);
        self.cursor.advance(0, cols);
    }

    fn move_backward(&mut self, spaces: i64) {
        println!("move_backward: {}", spaces);
        self.cursor.advance(0, -spaces);
    }

    fn identify_terminal(&mut self) { println!("identify_terminal"); }
    fn move_down_and_cr(&mut self, rows: i64) { println!("move_down_and_cr: {}", rows); }
    fn move_up_and_cr(&mut self, rows: i64) { println!("move_up_and_cr: {}", rows); }
    fn put_tab(&mut self, mut count: i64) {
        println!("put_tab: {}", count);

        let mut x = self.cursor_x();
        while x < self.grid.num_cols() as u16 && count != 0 {
            count -= 1;
            loop {
                if x == self.grid.num_cols() as u16 || self.tabs[x as usize] {
                    break;
                }
                x += 1;
            }
        }

        self.cursor.x = x;
    }

    /// Backspace `count` characters
    #[inline]
    fn backspace(&mut self, count: i64) {
        self.cursor.x -= 1;
        self.set_char(' ');
    }

    /// Carriage return
    #[inline]
    fn carriage_return(&mut self) {
        self.cursor.x = 0;
    }

    /// Linefeed
    #[inline]
    fn linefeed(&mut self) {
        println!("linefeed");
        // TODO handle scroll? not clear what parts of this the pty handle
        if self.cursor_y() + 1 == self.grid.num_rows() as u16 {
            self.grid.feed();
            self.clear_line(ansi::LineClearMode::Right);
        } else {
            self.cursor.y += 1;
        }
    }

    /// Set current position as a tabstop
    fn bell(&mut self) { println!("bell"); }
    fn substitute(&mut self) { println!("substitute"); }
    fn newline(&mut self) { println!("newline"); }
    fn set_horizontal_tabstop(&mut self) { println!("set_horizontal_tabstop"); }
    fn scroll_up(&mut self, rows: i64) { println!("scroll_up: {}", rows); }
    fn scroll_down(&mut self, rows: i64) { println!("scroll_down: {}", rows); }
    fn insert_blank_lines(&mut self, count: i64) { println!("insert_blank_lines: {}", count); }
    fn delete_lines(&mut self, count: i64) { println!("delete_lines: {}", count); }
    fn erase_chars(&mut self, count: i64) { println!("erase_chars: {}", count); }
    fn delete_chars(&mut self, count: i64) { println!("delete_chars: {}", count); }
    fn move_backward_tabs(&mut self, count: i64) { println!("move_backward_tabs: {}", count); }
    fn move_forward_tabs(&mut self, count: i64) { println!("move_forward_tabs: {}", count); }
    fn save_cursor_position(&mut self) { println!("save_cursor_position"); }
    fn restore_cursor_position(&mut self) { println!("restore_cursor_position"); }
    fn clear_line(&mut self, mode: ansi::LineClearMode) {
        println!("clear_line: {:?}", mode);
        match mode {
            ansi::LineClearMode::Right => {
                let cols = self.grid.num_cols();
                let row = &mut self.grid[self.cursor.y as usize];
                let start = self.cursor.x as usize;
                for col in start..cols {
                    row[col].c = ' ';
                }
            },
            _ => (),
        }
    }
    fn clear_screen(&mut self, mode: ansi::ClearMode) {
        println!("clear_screen: {:?}", mode);
        match mode {
            ansi::ClearMode::Below => {
                let start = self.cursor_y() as usize;
                let end = self.grid.num_rows();
                for i in start..end {
                    let row = &mut self.grid[i];
                    for cell in row.iter_mut() {
                        cell.c = ' ';
                    }
                }
            },
            ansi::ClearMode::All => {
                self.grid.clear();
            },
            _ => {
                panic!("ansi::ClearMode::Above not implemented");
            }
        }
    }
    fn clear_tabs(&mut self, mode: ansi::TabulationClearMode) { println!("clear_tabs: {:?}", mode); }
    fn reset_state(&mut self) { println!("reset_state"); }
    fn reverse_index(&mut self) {
        println!("reverse_index");
        // if cursor is at the top
        if self.cursor.y == 0 {
            self.grid.unfeed();
        } else {
            // can't wait for nonlexical lifetimes.. omg borrowck
            let x = self.cursor.x;
            let y = self.cursor.y;
            self.cursor.goto(x, y - 1);
        }
    }

    /// set a terminal attribute
    fn terminal_attribute(&mut self, attr: Attr) {
        match attr {
            Attr::DefaultForeground => {
                self.fg = DEFAULT_FG;
            },
            Attr::DefaultBackground => {
                self.bg = DEFAULT_BG;
            },
            Attr::Foreground(named_color) => {
                self.fg = COLORS[named_color as usize];
            },
            Attr::Background(named_color) => {
                self.bg = COLORS[named_color as usize];
            },
            Attr::ForegroundSpec(rgb) => {
                self.fg = rgb;
            },
            Attr::BackgroundSpec(rgb) => {
                self.bg = rgb;
            },
            Attr::Reset => {
                self.fg = DEFAULT_FG;
                self.bg = DEFAULT_BG;
                self.attr = CellFlags::empty();
            },
            Attr::Reverse => self.attr.insert(grid::INVERSE),
            Attr::CancelReverse => self.attr.remove(grid::INVERSE),
            Attr::Bold => self.attr.insert(grid::BOLD),
            Attr::CancelBoldDim => self.attr.remove(grid::BOLD),
            Attr::Italic => self.attr.insert(grid::ITALIC),
            Attr::CancelItalic => self.attr.remove(grid::ITALIC),
            Attr::Underscore => self.attr.insert(grid::UNDERLINE),
            Attr::CancelUnderline => self.attr.remove(grid::UNDERLINE),
            _ => {
                println!("Term got unhandled attr: {:?}", attr);
            }
        }
    }

    fn set_mode(&mut self, mode: ansi::Mode) {
        println!("set_mode: {:?}", mode);
        match mode {
            ansi::Mode::SwapScreenAndSetRestoreCursor => {
                self.swap_alt();
            }
        }
    }

    fn unset_mode(&mut self, mode: ansi::Mode) {
        println!("unset_mode: {:?}", mode);
        match mode {
            ansi::Mode::SwapScreenAndSetRestoreCursor => {
                self.swap_alt();
            }
        }
    }
}
<commit_msg>Add explicit bounds check when advancing cursor<commit_after>/// Exports the `Term` type which is a high-level API for the Grid
use std::sync::Arc;

use ansi::{self, Attr, DebugHandler};
use grid::{self, Grid, CellFlags};
use tty;
use ::Rgb;

/// tomorrow night bright
///
/// because contrast
pub static COLORS: &'static [Rgb] = &[
    Rgb {r: 0x00, g: 0x00, b: 0x00}, // Black
    Rgb {r: 0xd5, g: 0x4e, b: 0x53}, // Red
    Rgb {r: 0xb9, g: 0xca, b: 0x4a}, // Green
    Rgb {r: 0xe6, g: 0xc5, b: 0x47}, // Yellow
    Rgb {r: 0x7a, g: 0xa6, b: 0xda}, // Blue
    Rgb {r: 0xc3, g: 0x97, b: 0xd8}, // Magenta
    Rgb {r: 0x70, g: 0xc0, b: 0xba}, // Cyan
    Rgb {r: 0x42, g: 0x42, b: 0x42}, // White
    Rgb {r: 0x66, g: 0x66, b: 0x66}, // Bright black
    Rgb {r: 0xff, g: 0x33, b: 0x34}, // Bright red
    Rgb {r: 0x9e, g: 0xc4, b: 0x00}, // Bright green
    Rgb {r: 0xe7, g: 0xc5, b: 0x47}, // Bright yellow
    Rgb {r: 0x7a, g: 0xa6, b: 0xda}, // Bright blue
    Rgb {r: 0xb7, g: 0x7e, b: 0xe0}, // Bright magenta
    Rgb {r: 0x54, g: 0xce, b: 0xd6}, // Bright cyan
    Rgb {r: 0x2a, g: 0x2a, b: 0x2a}, // Bright white
];

pub const CURSOR_SHAPE: char = '█';

pub const DEFAULT_FG: Rgb = Rgb { r: 0xea, g: 0xea, b: 0xea};
pub const DEFAULT_BG: Rgb = Rgb { r: 0, g: 0, b: 0};
pub const TAB_SPACES: usize = 8;

/// State for cursor
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Cursor {
    pub x: u16,
    pub y: u16,
}

impl Default for Cursor {
    fn default() -> Cursor {
        Cursor { x: 0, y: 0 }
    }
}

impl Cursor {
    pub fn goto(&mut self, x: u16, y: u16) {
        self.x = x;
        self.y = y;
    }

    pub fn advance(&mut self, rows: i64, cols: i64) {
        self.x = (self.x as i64 + cols) as u16;
        self.y = (self.y as i64 + rows) as u16;
    }
}

struct Mover<'a> {
    cursor: &'a mut Cursor,
}

pub struct Term {
    /// The grid
    grid: Grid,

    /// Alternate grid
    alt_grid: Grid,

    /// Alt is active
    alt: bool,

    /// Reference to the underlying tty
    tty: tty::Tty,

    /// The cursor
    cursor: Cursor,

    /// Alt cursor
    alt_cursor: Cursor,

    /// Active foreground color
    fg: Rgb,

    /// Active background color
    bg: Rgb,

    /// Tabstops
    tabs: Vec<bool>,

    /// Cell attributes
    attr: grid::CellFlags,
}

impl Term {
    pub fn new(tty: tty::Tty, grid: Grid) -> Term {

        let mut tabs = (0..grid.num_cols()).map(|i| i % TAB_SPACES == 0)
                                       .collect::<Vec<bool>>();
        tabs[0] = false;

        let alt = grid.clone();

        Term {
            grid: grid,
            alt_grid: alt,
            alt: false,
            cursor: Cursor::default(),
            alt_cursor: Cursor::default(),
            fg: DEFAULT_FG,
            bg: DEFAULT_BG,
            tty: tty,
            tabs: tabs,
            attr: CellFlags::empty(),
        }
    }

    pub fn grid(&self) -> &Grid {
        &self.grid
    }

    pub fn swap_alt(&mut self) {
        self.alt = !self.alt;
        ::std::mem::swap(&mut self.grid, &mut self.alt_grid);
        ::std::mem::swap(&mut self.cursor, &mut self.alt_cursor);

        if self.alt {
            self.grid.clear();
        }
    }

    pub fn resize(&mut self) {
        unimplemented!();
    }

    #[inline]
    pub fn cursor_x(&self) -> u16 {
        self.cursor.x
    }

    #[inline]
    pub fn cursor_y(&self) -> u16 {
        self.cursor.y
    }

    #[inline]
    pub fn cursor(&self) -> Cursor {
        self.cursor
    }

    /// Set character in current cursor position
    fn set_char(&mut self, c: char) {
        if self.cursor.x == self.grid.num_cols() as u16 {
            self.cursor.y += 1;
            self.cursor.x = 0;
        }

        if self.cursor.y == self.grid.num_rows() as u16 {
            panic!("cursor fell off grid");
        }

        let cell = &mut self.grid[self.cursor];
        cell.c = c;
        cell.fg = self.fg;
        cell.bg = self.bg;
        cell.flags = self.attr;
    }

    /// Advance to next line
    fn newline_c(&mut self, count: u16) {
        // TODO handle scroll
        self.cursor.x = 0;
        self.cursor.y += 1;
    }
}

impl ansi::Handler for Term {
    /// A character to be displayed
    #[inline]
    fn input(&mut self, c: char) {
        self.set_char(c);
        self.cursor.x += 1;
    }

    fn goto(&mut self, x: i64, y: i64) {
        println!("goto: x={}, y={}", x, y);
        self.cursor.goto(x as u16, y as u16);
    }
    fn goto_row(&mut self, y: i64) {
        println!("goto_row: {}", y);
        let x = self.cursor_x();
        self.cursor.goto(x, y as u16);
    }
    fn goto_col(&mut self, x: i64) {
        println!("goto_col: {}", x);
        let y = self.cursor_y();
        self.cursor.goto(x as u16, y);
    }

    fn insert_blank(&mut self, num: i64) { println!("insert_blank: {}", num); }

    fn move_up(&mut self, rows: i64) {
        println!("move_up: {}", rows);
        self.cursor.advance(-rows, 0);
    }

    fn move_down(&mut self, rows: i64) {
        println!("move_down: {}", rows);
        self.cursor.advance(rows, 0);
    }

    fn move_forward(&mut self, cols: i64) {
        println!("move_forward: {}", cols);
        self.cursor.advance(0, cols);
    }

    fn move_backward(&mut self, spaces: i64) {
        println!("move_backward: {}", spaces);
        self.cursor.advance(0, -spaces);
    }

    fn identify_terminal(&mut self) { println!("identify_terminal"); }
    fn move_down_and_cr(&mut self, rows: i64) { println!("move_down_and_cr: {}", rows); }
    fn move_up_and_cr(&mut self, rows: i64) { println!("move_up_and_cr: {}", rows); }
    fn put_tab(&mut self, mut count: i64) {
        println!("put_tab: {}", count);

        let mut x = self.cursor_x();
        while x < self.grid.num_cols() as u16 && count != 0 {
            count -= 1;
            loop {
                if x == self.grid.num_cols() as u16 || self.tabs[x as usize] {
                    break;
                }
                x += 1;
            }
        }

        self.cursor.x = x;
    }

    /// Backspace `count` characters
    #[inline]
    fn backspace(&mut self, count: i64) {
        self.cursor.x -= 1;
        self.set_char(' ');
    }

    /// Carriage return
    #[inline]
    fn carriage_return(&mut self) {
        self.cursor.x = 0;
    }

    /// Linefeed
    #[inline]
    fn linefeed(&mut self) {
        println!("linefeed");
        // TODO handle scroll? not clear what parts of this the pty handle
        if self.cursor_y() + 1 == self.grid.num_rows() as u16 {
            self.grid.feed();
            self.clear_line(ansi::LineClearMode::Right);
        } else {
            self.cursor.y += 1;
        }
    }

    /// Set current position as a tabstop
    fn bell(&mut self) { println!("bell"); }
    fn substitute(&mut self) { println!("substitute"); }
    fn newline(&mut self) { println!("newline"); }
    fn set_horizontal_tabstop(&mut self) { println!("set_horizontal_tabstop"); }
    fn scroll_up(&mut self, rows: i64) { println!("scroll_up: {}", rows); }
    fn scroll_down(&mut self, rows: i64) { println!("scroll_down: {}", rows); }
    fn insert_blank_lines(&mut self, count: i64) { println!("insert_blank_lines: {}", count); }
    fn delete_lines(&mut self, count: i64) { println!("delete_lines: {}", count); }
    fn erase_chars(&mut self, count: i64) { println!("erase_chars: {}", count); }
    fn delete_chars(&mut self, count: i64) { println!("delete_chars: {}", count); }
    fn move_backward_tabs(&mut self, count: i64) { println!("move_backward_tabs: {}", count); }
    fn move_forward_tabs(&mut self, count: i64) { println!("move_forward_tabs: {}", count); }
    fn save_cursor_position(&mut self) { println!("save_cursor_position"); }
    fn restore_cursor_position(&mut self) { println!("restore_cursor_position"); }
    fn clear_line(&mut self, mode: ansi::LineClearMode) {
        println!("clear_line: {:?}", mode);
        match mode {
            ansi::LineClearMode::Right => {
                let cols = self.grid.num_cols();
                let row = &mut self.grid[self.cursor.y as usize];
                let start = self.cursor.x as usize;
                for col in start..cols {
                    row[col].c = ' ';
                }
            },
            _ => (),
        }
    }
    fn clear_screen(&mut self, mode: ansi::ClearMode) {
        println!("clear_screen: {:?}", mode);
        match mode {
            ansi::ClearMode::Below => {
                let start = self.cursor_y() as usize;
                let end = self.grid.num_rows();
                for i in start..end {
                    let row = &mut self.grid[i];
                    for cell in row.iter_mut() {
                        cell.c = ' ';
                    }
                }
            },
            ansi::ClearMode::All => {
                self.grid.clear();
            },
            _ => {
                panic!("ansi::ClearMode::Above not implemented");
            }
        }
    }
    fn clear_tabs(&mut self, mode: ansi::TabulationClearMode) { println!("clear_tabs: {:?}", mode); }
    fn reset_state(&mut self) { println!("reset_state"); }
    fn reverse_index(&mut self) {
        println!("reverse_index");
        // if cursor is at the top
        if self.cursor.y == 0 {
            self.grid.unfeed();
        } else {
            // can't wait for nonlexical lifetimes.. omg borrowck
            let x = self.cursor.x;
            let y = self.cursor.y;
            self.cursor.goto(x, y - 1);
        }
    }

    /// set a terminal attribute
    fn terminal_attribute(&mut self, attr: Attr) {
        match attr {
            Attr::DefaultForeground => {
                self.fg = DEFAULT_FG;
            },
            Attr::DefaultBackground => {
                self.bg = DEFAULT_BG;
            },
            Attr::Foreground(named_color) => {
                self.fg = COLORS[named_color as usize];
            },
            Attr::Background(named_color) => {
                self.bg = COLORS[named_color as usize];
            },
            Attr::ForegroundSpec(rgb) => {
                self.fg = rgb;
            },
            Attr::BackgroundSpec(rgb) => {
                self.bg = rgb;
            },
            Attr::Reset => {
                self.fg = DEFAULT_FG;
                self.bg = DEFAULT_BG;
                self.attr = CellFlags::empty();
            },
            Attr::Reverse => self.attr.insert(grid::INVERSE),
            Attr::CancelReverse => self.attr.remove(grid::INVERSE),
            Attr::Bold => self.attr.insert(grid::BOLD),
            Attr::CancelBoldDim => self.attr.remove(grid::BOLD),
            Attr::Italic => self.attr.insert(grid::ITALIC),
            Attr::CancelItalic => self.attr.remove(grid::ITALIC),
            Attr::Underscore => self.attr.insert(grid::UNDERLINE),
            Attr::CancelUnderline => self.attr.remove(grid::UNDERLINE),
            _ => {
                println!("Term got unhandled attr: {:?}", attr);
            }
        }
    }

    fn set_mode(&mut self, mode: ansi::Mode) {
        println!("set_mode: {:?}", mode);
        match mode {
            ansi::Mode::SwapScreenAndSetRestoreCursor => {
                self.swap_alt();
            }
        }
    }

    fn unset_mode(&mut self, mode: ansi::Mode) {
        println!("unset_mode: {:?}", mode);
        match mode {
            ansi::Mode::SwapScreenAndSetRestoreCursor => {
                self.swap_alt();
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate url;

use url::percent_encoding::{lossy_utf8_percent_decode};
use std::env;
use std::io::{self, Read};

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() < 2 {
        let stdin = io::stdin();
        loop {
            let mut buffer = String::new();
            match stdin.read_line(&mut buffer) {
                Ok(len) => {
                    if len > 0 {
                        print!("{}", decode(&buffer))
                    } else {
                        return
                    }
                }
                Err(_) => return,
            }
        }
    }
    println!("{}", decode(&args[1]));
}

fn decode(str: &String) -> String {
    return lossy_utf8_percent_decode(str.as_bytes());
}
<commit_msg>Remove compiler warning<commit_after>extern crate url;

use url::percent_encoding::{lossy_utf8_percent_decode};
use std::env;
use std::io::{self};

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() < 2 {
        let stdin = io::stdin();
        loop {
            let mut buffer = String::new();
            match stdin.read_line(&mut buffer) {
                Ok(len) => {
                    if len > 0 {
                        print!("{}", decode(&buffer))
                    } else {
                        return
                    }
                }
                Err(_) => return,
            }
        }
    }
    println!("{}", decode(&args[1]));
}

fn decode(str: &String) -> String {
    return lossy_utf8_percent_decode(str.as_bytes());
}
<|endoftext|>


<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

pub unsafe trait Wrapper {

    type Raw: Sized;

    #[inline]
    fn as_ptr(&self) -> *const <Self as Wrapper>::Raw {
        self as *const _ as *const <Self as Wrapper>::Raw
    }

    #[inline]
    unsafe fn as_mut_ptr(&self) -> *mut <Self as Wrapper>::Raw {
        self as *const _ as *mut <Self as Wrapper>::Raw
    }
}

#[inline]
pub unsafe fn from_raw<'a, T>(ptr: *const <T as Wrapper>::Raw) -> &'a T
    where T: Wrapper
{
    &*(ptr as *const T)
}
<commit_msg>Restrict trait Wrapper to sized types<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

pub unsafe trait Wrapper : Sized {

    type Raw: Sized;

    #[inline]
    fn as_ptr(&self) -> *const <Self as Wrapper>::Raw {
        self as *const _ as *const <Self as Wrapper>::Raw
    }

    #[inline]
    unsafe fn as_mut_ptr(&self) -> *mut <Self as Wrapper>::Raw {
        self as *const _ as *mut <Self as Wrapper>::Raw
    }
}

#[inline]
pub unsafe fn from_raw<'a, T>(ptr: *const <T as Wrapper>::Raw) -> &'a T
    where T: Wrapper
{
    &*(ptr as *const T)
}
<|endoftext|>


<commit_before>use super::prelude::*;
use stencila_schema::Node;

/// Override of macro to implement `from_value` for all node types
macro_rules! patchable_node {
    ($( $variant:path )*) => {
        impl Patchable for Node {
            patchable_variants_resolve!($( $variant )*);
            patchable_variants_find!($( $variant )*);

            patchable_is_same!();
            patchable_variants_is_equal!($( $variant )*);
            patchable_variants_hash!($( $variant )*);

            patchable_diff!();
            patchable_variants_diff_same!($( $variant )*);

            patchable_variants_apply_add!($( $variant )*);
            patchable_variants_apply_remove!($( $variant )*);
            patchable_variants_apply_replace!($( $variant )*);
            patchable_variants_apply_move!($( $variant )*);
            patchable_variants_apply_transform!($( $variant )*);

            fn from_value(value: &Value) -> Result<Self>
            where
                Self: Clone + Sized + 'static,
            {
                if let Some(value) = value.downcast_ref::<Self>() {
                    return Ok(value.clone());
                } else if let Some(value) = value.downcast_ref::<serde_json::Value>() {
                    if let Some(string) = value.as_str() {
                        return Ok(Node::String(string.to_string()));
                    }
                    if let Some(number) = value.as_f64() {
                        return Ok(Node::Number(number));
                    }
                    if let Some(integer) = value.as_i64() {
                        return Ok(Node::Integer(integer));
                    }
                    if let Some(boolean) = value.as_bool() {
                        return Ok(Node::Boolean(boolean));
                    }
                }
                bail!(invalid_patch_value::<Self>())
            }
        }
    };
}

patchable_node!(
    Node::Article

    Node::Null
    Node::Boolean
    Node::Integer
    Node::Number
    Node::String

    Node::CodeBlock
);
<commit_msg>chore(Patches): Add more variants for `Node` (for use in outputs)<commit_after>use super::prelude::*;
use stencila_schema::Node;

/// Override of macro to implement `from_value` for all node types
macro_rules! patchable_node {
    ($( $variant:path )*) => {
        impl Patchable for Node {
            patchable_variants_resolve!($( $variant )*);
            patchable_variants_find!($( $variant )*);

            patchable_is_same!();
            patchable_variants_is_equal!($( $variant )*);
            patchable_variants_hash!($( $variant )*);

            patchable_diff!();
            patchable_variants_diff_same!($( $variant )*);

            patchable_variants_apply_add!($( $variant )*);
            patchable_variants_apply_remove!($( $variant )*);
            patchable_variants_apply_replace!($( $variant )*);
            patchable_variants_apply_move!($( $variant )*);
            patchable_variants_apply_transform!($( $variant )*);

            fn from_value(value: &Value) -> Result<Self>
            where
                Self: Clone + Sized + 'static,
            {
                if let Some(value) = value.downcast_ref::<Self>() {
                    return Ok(value.clone());
                } else if let Some(value) = value.downcast_ref::<serde_json::Value>() {
                    if let Some(string) = value.as_str() {
                        return Ok(Node::String(string.to_string()));
                    }
                    if let Some(number) = value.as_f64() {
                        return Ok(Node::Number(number));
                    }
                    if let Some(integer) = value.as_i64() {
                        return Ok(Node::Integer(integer));
                    }
                    if let Some(boolean) = value.as_bool() {
                        return Ok(Node::Boolean(boolean));
                    }
                }
                bail!(invalid_patch_value::<Self>())
            }
        }
    };
}

// TODO: Commented out node types need methods implemented to be
// able to be included as variants here
patchable_node!(
    //Node::Array
    Node::Article
    //Node::AudioObject
    Node::Boolean
    Node::Cite
    Node::CiteGroup
    //Node::Claim
    Node::CodeBlock
    Node::CodeChunk
    Node::CodeExpression
    Node::CodeFragment
    Node::Delete
    Node::Emphasis
    //Node::Figure
    Node::Heading
    //Node::ImageObject
    Node::Integer
    Node::Link
    Node::List
    Node::MathBlock
    Node::MathFragment
    Node::NontextualAnnotation
    Node::Note
    Node::Null
    Node::Number
    //Node::Object
    Node::Paragraph
    Node::Quote
    Node::QuoteBlock
    Node::String
    Node::Strong
    Node::Subscript
    Node::Superscript
    //Node::Table
    Node::ThematicBreak
    //Node::VideoObject
);
<|endoftext|>


<commit_before>//! Neural Network module
//!
//! Contains implementation of simple feed forward neural network.
//!
//! # Usage
//!
//! ```
//! use rusty_machine::learning::nnet::NeuralNet;
//! use rusty_machine::linalg::matrix::Matrix;
//! use rusty_machine::learning::SupModel;
//!
//! let data = Matrix::new(5,3, vec![1.,1.,1.,2.,2.,2.,3.,3.,3.,
//! 								4.,4.,4.,5.,5.,5.,]);
//! let outputs = Matrix::new(5,3, vec![1.,0.,0.,0.,1.,0.,0.,0.,1.,
//! 									0.,0.,1.,0.,0.,1.]);
//!
//! let layers = &[3,5,11,7,3];
//! let mut model = NeuralNet::default(layers);
//!
//! model.train(&data, &outputs);
//!
//! let test_data = Matrix::new(2,3, vec![1.5,1.5,1.5,5.1,5.1,5.1]);
//!
//! model.predict(&test_data);
//! ```

use linalg::matrix::Matrix;
use learning::SupModel;
use learning::toolkit::activ_fn;
use learning::toolkit::activ_fn::ActivationFunc;
use learning::toolkit::cost_fn;
use learning::toolkit::cost_fn::CostFunc;
use learning::optim::{Optimizable, OptimAlgorithm};
use learning::optim::grad_desc::GradientDesc;

use rand::{Rng, thread_rng};

/// Neural Network struct
pub struct NeuralNet<'a, T: Criterion> {
    layer_sizes: &'a [usize],
    weights: Vec<f64>,
    gd: GradientDesc,
    criterion: T,
}

impl<'a> NeuralNet<'a, BCECriterion> {

    /// Creates a neural network with the specified layer sizes.
    ///
    /// Uses the default settings (gradient descent and sigmoid activation function).
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::nnet::NeuralNet;
    ///
    /// // Create a neural net with 4 layers, 3 neurons in each.
    /// let layers = &[3; 4];
    /// let mut a = NeuralNet::default(layers);
    /// ```
    pub fn default(layer_sizes: &[usize]) -> NeuralNet<BCECriterion> {
        NeuralNet {
            layer_sizes: layer_sizes,
            weights: NeuralNet::<BCECriterion>::create_weights(layer_sizes),
            gd: GradientDesc::default(),
            criterion: BCECriterion,
        }
    }
}
impl<'a, T: Criterion> NeuralNet<'a, T> {
    /// Create a new neural network with the specified layer sizes.
    ///
    /// The layer sizes slice should include the input, hidden layers, and output layer sizes.
    /// The type of activation function must be specified.
    ///
    /// Currently defaults to simple batch Gradient Descent for optimization.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::nnet::BCECriterion;
    /// use rusty_machine::learning::nnet::NeuralNet;
    ///
    /// // Create a neural net with 4 layers, 3 neurons in each.
    /// let layers = &[3; 4];
    /// let mut a = NeuralNet::new(layers, BCECriterion);
    /// ```
    pub fn new(layer_sizes: &[usize], criterion: T) -> NeuralNet<T> {
        NeuralNet {
            layer_sizes: layer_sizes,
            weights: NeuralNet::<T>::create_weights(layer_sizes),
            gd: GradientDesc::default(),
            criterion: criterion,
        }
    }

    /// Creates initial weights for all neurons in the network.
    fn create_weights(layer_sizes: &[usize]) -> Vec<f64> {
        let total_layers = layer_sizes.len();

        let mut capacity = 0usize;

        for l in 0..total_layers - 1 {
            capacity += (layer_sizes[l] + 1) * layer_sizes[l + 1]
        }

        let mut layers = Vec::with_capacity(capacity);

        for l in 0..total_layers - 1 {
            layers.append(&mut NeuralNet::<T>::initialize_weights(layer_sizes[l] + 1,
                                                             layer_sizes[l + 1]));
        }

        layers
    }

    /// Initializes the weights for a single layer in the network.
    fn initialize_weights(rows: usize, cols: usize) -> Vec<f64> {
        let mut weights = Vec::with_capacity(rows * cols);
        let eps_init = (6f64 / (rows + cols) as f64).sqrt();

        let mut rng = thread_rng();

        for _i in 0..rows * cols {
            let w = (rng.gen_range(0f64, 1f64) * 2f64 * eps_init) - eps_init;
            weights.push(w);
        }

        weights
    }

    /// Gets matrix of weights between specified layer and forward layer for the weights.
    fn get_layer_weights(&self, weights: &[f64], idx: usize) -> Matrix<f64> {
        assert!(idx < self.layer_sizes.len() - 1);

        // Check that the weights are the right size.
        let mut full_size = 0usize;
        for l in 0..self.layer_sizes.len() - 1 {
            full_size += (self.layer_sizes[l] + 1) * self.layer_sizes[l + 1];
        }

        assert_eq!(full_size, weights.len());

        let mut start = 0usize;

        for l in 0..idx {
            start += (self.layer_sizes[l] + 1) * self.layer_sizes[l + 1]
        }

        let capacity = (self.layer_sizes[idx] + 1) * self.layer_sizes[idx + 1];

        let mut layer_weights = Vec::with_capacity((self.layer_sizes[idx] + 1) *
                                                   self.layer_sizes[idx + 1]);
        unsafe {
            for i in start..start + capacity {
                layer_weights.push(*weights.get_unchecked(i));
            }
        }

        Matrix::new(self.layer_sizes[idx] + 1,
                    self.layer_sizes[idx + 1],
                    layer_weights)

    }

    /// Gets matrix of weights between specified layer and forward layer.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::nnet::NeuralNet;
    ///
    /// // Create a neural net with 4 layers, 3 neurons in each.
    /// let layers = &[3; 4];
    /// let mut a = NeuralNet::default(layers);
    ///
    /// let w = &a.get_net_weights(2);
    /// assert_eq!(w.rows(), 4);
    /// assert_eq!(w.cols(), 3);
    /// ```
    pub fn get_net_weights(&self, idx: usize) -> Matrix<f64> {
        self.get_layer_weights(&self.weights[..], idx)
    }

    /// Compute the gradient using the back propagation algorithm.
    fn compute_grad(&self, weights: &[f64], data: &Matrix<f64>, outputs: &Matrix<f64>) -> (f64, Vec<f64>) {
        assert_eq!(data.cols(), self.layer_sizes[0]);

        let mut forward_weights = Vec::with_capacity(self.layer_sizes.len() - 1);
        let mut activations = Vec::with_capacity(self.layer_sizes.len());

        let net_data = Matrix::ones(data.rows(), 1).hcat(data);

        activations.push(net_data.clone());

        // Forward propagation
        {
            let mut z = net_data * self.get_layer_weights(weights, 0);
            forward_weights.push(z.clone());

            for l in 1..self.layer_sizes.len() - 1 {
                let mut a = self.criterion.activate(z.clone());
                let ones = Matrix::ones(a.rows(), 1);

                a = ones.hcat(&a);
                activations.push(a.clone());
                z = a * self.get_layer_weights(weights, l);
                forward_weights.push(z.clone());
            }

            activations.push(self.criterion.activate(z));
        }

        // Compute cost using the last activation.

        let mut deltas = Vec::with_capacity(self.layer_sizes.len() - 1);
        // Backward propagation
        {
            // Take GRAD_cost to compute this delta.
            let mut delta = self.criterion.cost_grad(&activations[self.layer_sizes.len() - 1], outputs);

            deltas.push(delta.clone());

            for l in (1..self.layer_sizes.len() - 1).rev() {
                let mut z = forward_weights[l - 1].clone();
                let ones = Matrix::ones(z.rows(), 1);
                z = ones.hcat(&z);

                let g = self.criterion.grad_activ(z);
                delta = (delta * self.get_layer_weights(weights, l).transpose()).elemul(&g);

                let non_one_rows = &(1..delta.cols()).collect::<Vec<usize>>()[..];
                delta = delta.select_cols(non_one_rows);
                deltas.push(delta.clone());
            }
        }

        let mut grad = Vec::with_capacity(self.layer_sizes.len() - 1);
        let mut capacity = 0;

        for l in 0..self.layer_sizes.len() - 1 {
            let g = deltas[self.layer_sizes.len() - 2 - l].transpose() * activations[l].clone();
            capacity += g.cols() * g.rows();
            grad.push(g / (data.rows() as f64));
        }

        let mut gradients = Vec::with_capacity(capacity);

        for g in grad {
            gradients.append(&mut g.data.clone());
        }

        (self.criterion.cost(&activations[activations.len() - 1], outputs), gradients)
    }

    /// Forward propagation of the model weights to get the outputs.
    fn forward_prop(&self, data: &Matrix<f64>) -> Matrix<f64> {
        assert_eq!(data.cols(), self.layer_sizes[0]);

        let net_data = Matrix::ones(data.rows(), 1).hcat(data);

        let mut z = net_data * self.get_net_weights(0);
        let mut a = self.criterion.activate(z.clone());

        for l in 1..self.layer_sizes.len() - 1 {
            let ones = Matrix::ones(a.rows(), 1);
            a = ones.hcat(&a);
            z = a * self.get_net_weights(l);
            a = self.criterion.activate(z.clone());
        }

        a
    }
}

impl<'a, T: Criterion> Optimizable for NeuralNet<'a, T> {
    type Data = Matrix<f64>;
	type Target = Matrix<f64>;

    /// Compute the gradient of the neural network.
    fn compute_grad(&self, params: &[f64], data: &Matrix<f64>, target: &Matrix<f64>) -> (f64, Vec<f64>) {
        self.compute_grad(params, data, target)
    }
}

impl<'a, T: Criterion> SupModel<Matrix<f64>, Matrix<f64>> for NeuralNet<'a, T> {
    /// Predict neural network output using forward propagation.
    fn predict(&self, data: &Matrix<f64>) -> Matrix<f64> {
        self.forward_prop(data)
    }

    /// Train the model using gradient optimization and back propagation.
    fn train(&mut self, data: &Matrix<f64>, values: &Matrix<f64>) {
        let start = self.weights.clone();
        let optimal_w = self.gd.optimize(self, &start[..], data, values);
        self.weights = optimal_w;
    }
}

pub trait Criterion {
    type ActFunc: ActivationFunc;
    type Cost: CostFunc<Matrix<f64>>;

    fn activate(&self, mat: Matrix<f64>) -> Matrix<f64> {
        mat.apply(&Self::ActFunc::func)
    }

    fn grad_activ(&self, mat: Matrix<f64>) -> Matrix<f64> {
        mat.apply(&Self::ActFunc::func_grad)
    }

    fn cost(&self, output: &Matrix<f64>, target: &Matrix<f64>) -> f64 {
        Self::Cost::cost(output, target)
    }

    fn cost_grad(&self, output: &Matrix<f64>, target: &Matrix<f64>) -> Matrix<f64> {
        Self::Cost::grad_cost(output, target)
    }
}

pub struct BCECriterion;

impl Criterion for BCECriterion {
    type ActFunc = activ_fn::Sigmoid;
    type Cost = cost_fn::CrossEntropyError;
}

pub struct MSECriterion;

impl Criterion for MSECriterion {
    type ActFunc = activ_fn::Linear;
    type Cost = cost_fn::MeanSqError;
}<commit_msg>Switching to conjugate GD by default. More work needed on structure.<commit_after>//! Neural Network module
//!
//! Contains implementation of simple feed forward neural network.
//!
//! # Usage
//!
//! ```
//! use rusty_machine::learning::nnet::NeuralNet;
//! use rusty_machine::linalg::matrix::Matrix;
//! use rusty_machine::learning::SupModel;
//!
//! let data = Matrix::new(5,3, vec![1.,1.,1.,2.,2.,2.,3.,3.,3.,
//! 								4.,4.,4.,5.,5.,5.,]);
//! let outputs = Matrix::new(5,3, vec![1.,0.,0.,0.,1.,0.,0.,0.,1.,
//! 									0.,0.,1.,0.,0.,1.]);
//!
//! let layers = &[3,5,11,7,3];
//! let mut model = NeuralNet::default(layers);
//!
//! model.train(&data, &outputs);
//!
//! let test_data = Matrix::new(2,3, vec![1.5,1.5,1.5,5.1,5.1,5.1]);
//!
//! model.predict(&test_data);
//! ```

use linalg::matrix::Matrix;
use learning::SupModel;
use learning::toolkit::activ_fn;
use learning::toolkit::activ_fn::ActivationFunc;
use learning::toolkit::cost_fn;
use learning::toolkit::cost_fn::CostFunc;
use learning::optim::{Optimizable, OptimAlgorithm};
use learning::optim::fmincg::ConjugateGD;

use rand::{Rng, thread_rng};

/// Neural Network struct
pub struct NeuralNet<'a, T: Criterion> {
    layer_sizes: &'a [usize],
    weights: Vec<f64>,
    gd: ConjugateGD,
    criterion: T,
}

impl<'a> NeuralNet<'a, BCECriterion> {

    /// Creates a neural network with the specified layer sizes.
    ///
    /// Uses the default settings (gradient descent and sigmoid activation function).
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::nnet::NeuralNet;
    ///
    /// // Create a neural net with 4 layers, 3 neurons in each.
    /// let layers = &[3; 4];
    /// let mut a = NeuralNet::default(layers);
    /// ```
    pub fn default(layer_sizes: &[usize]) -> NeuralNet<BCECriterion> {
        NeuralNet {
            layer_sizes: layer_sizes,
            weights: NeuralNet::<BCECriterion>::create_weights(layer_sizes),
            gd: ConjugateGD::default(),
            criterion: BCECriterion,
        }
    }
}
impl<'a, T: Criterion> NeuralNet<'a, T> {
    /// Create a new neural network with the specified layer sizes.
    ///
    /// The layer sizes slice should include the input, hidden layers, and output layer sizes.
    /// The type of activation function must be specified.
    ///
    /// Currently defaults to simple batch Gradient Descent for optimization.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::nnet::BCECriterion;
    /// use rusty_machine::learning::nnet::NeuralNet;
    ///
    /// // Create a neural net with 4 layers, 3 neurons in each.
    /// let layers = &[3; 4];
    /// let mut a = NeuralNet::new(layers, BCECriterion);
    /// ```
    pub fn new(layer_sizes: &[usize], criterion: T) -> NeuralNet<T> {
        NeuralNet {
            layer_sizes: layer_sizes,
            weights: NeuralNet::<T>::create_weights(layer_sizes),
            gd: ConjugateGD::default(),
            criterion: criterion,
        }
    }

    /// Creates initial weights for all neurons in the network.
    fn create_weights(layer_sizes: &[usize]) -> Vec<f64> {
        let total_layers = layer_sizes.len();

        let mut capacity = 0usize;

        for l in 0..total_layers - 1 {
            capacity += (layer_sizes[l] + 1) * layer_sizes[l + 1]
        }

        let mut layers = Vec::with_capacity(capacity);

        for l in 0..total_layers - 1 {
            layers.append(&mut NeuralNet::<T>::initialize_weights(layer_sizes[l] + 1,
                                                             layer_sizes[l + 1]));
        }

        layers
    }

    /// Initializes the weights for a single layer in the network.
    fn initialize_weights(rows: usize, cols: usize) -> Vec<f64> {
        let mut weights = Vec::with_capacity(rows * cols);
        let eps_init = (6f64 / (rows + cols) as f64).sqrt();

        let mut rng = thread_rng();

        for _i in 0..rows * cols {
            let w = (rng.gen_range(0f64, 1f64) * 2f64 * eps_init) - eps_init;
            weights.push(w);
        }

        weights
    }

    /// Gets matrix of weights between specified layer and forward layer for the weights.
    fn get_layer_weights(&self, weights: &[f64], idx: usize) -> Matrix<f64> {
        assert!(idx < self.layer_sizes.len() - 1);

        // Check that the weights are the right size.
        let mut full_size = 0usize;
        for l in 0..self.layer_sizes.len() - 1 {
            full_size += (self.layer_sizes[l] + 1) * self.layer_sizes[l + 1];
        }

        assert_eq!(full_size, weights.len());

        let mut start = 0usize;

        for l in 0..idx {
            start += (self.layer_sizes[l] + 1) * self.layer_sizes[l + 1]
        }

        let capacity = (self.layer_sizes[idx] + 1) * self.layer_sizes[idx + 1];

        let mut layer_weights = Vec::with_capacity((self.layer_sizes[idx] + 1) *
                                                   self.layer_sizes[idx + 1]);
        unsafe {
            for i in start..start + capacity {
                layer_weights.push(*weights.get_unchecked(i));
            }
        }

        Matrix::new(self.layer_sizes[idx] + 1,
                    self.layer_sizes[idx + 1],
                    layer_weights)

    }

    /// Gets matrix of weights between specified layer and forward layer.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::nnet::NeuralNet;
    ///
    /// // Create a neural net with 4 layers, 3 neurons in each.
    /// let layers = &[3; 4];
    /// let mut a = NeuralNet::default(layers);
    ///
    /// let w = &a.get_net_weights(2);
    /// assert_eq!(w.rows(), 4);
    /// assert_eq!(w.cols(), 3);
    /// ```
    pub fn get_net_weights(&self, idx: usize) -> Matrix<f64> {
        self.get_layer_weights(&self.weights[..], idx)
    }

    /// Compute the gradient using the back propagation algorithm.
    fn compute_grad(&self, weights: &[f64], data: &Matrix<f64>, outputs: &Matrix<f64>) -> (f64, Vec<f64>) {
        assert_eq!(data.cols(), self.layer_sizes[0]);

        let mut forward_weights = Vec::with_capacity(self.layer_sizes.len() - 1);
        let mut activations = Vec::with_capacity(self.layer_sizes.len());

        let net_data = Matrix::ones(data.rows(), 1).hcat(data);

        activations.push(net_data.clone());

        // Forward propagation
        {
            let mut z = net_data * self.get_layer_weights(weights, 0);
            forward_weights.push(z.clone());

            for l in 1..self.layer_sizes.len() - 1 {
                let mut a = self.criterion.activate(z.clone());
                let ones = Matrix::ones(a.rows(), 1);

                a = ones.hcat(&a);
                activations.push(a.clone());
                z = a * self.get_layer_weights(weights, l);
                forward_weights.push(z.clone());
            }

            activations.push(self.criterion.activate(z));
        }

        // Compute cost using the last activation.

        let mut deltas = Vec::with_capacity(self.layer_sizes.len() - 1);
        // Backward propagation
        {
            let z = forward_weights[self.layer_sizes.len() - 2].clone();
            let g = self.criterion.grad_activ(z);

            // Take GRAD_cost to compute this delta.
            let mut delta = self.criterion.cost_grad(&activations[self.layer_sizes.len() - 1], outputs).elemul(&g);

            deltas.push(delta.clone());

            for l in (1..self.layer_sizes.len() - 1).rev() {
                let mut z = forward_weights[l - 1].clone();
                let ones = Matrix::ones(z.rows(), 1);
                z = ones.hcat(&z);

                let g = self.criterion.grad_activ(z);
                delta = (delta * self.get_layer_weights(weights, l).transpose()).elemul(&g);

                let non_one_rows = &(1..delta.cols()).collect::<Vec<usize>>()[..];
                delta = delta.select_cols(non_one_rows);
                deltas.push(delta.clone());
            }
        }

        let mut grad = Vec::with_capacity(self.layer_sizes.len() - 1);
        let mut capacity = 0;

        for l in 0..self.layer_sizes.len() - 1 {
            let g = deltas[self.layer_sizes.len() - 2 - l].transpose() * activations[l].clone();
            capacity += g.cols() * g.rows();
            grad.push(g / (data.rows() as f64));
        }

        let mut gradients = Vec::with_capacity(capacity);

        for g in grad {
            gradients.append(&mut g.data.clone());
        }

        (self.criterion.cost(&activations[activations.len() - 1], outputs), gradients)
    }

    /// Forward propagation of the model weights to get the outputs.
    fn forward_prop(&self, data: &Matrix<f64>) -> Matrix<f64> {
        assert_eq!(data.cols(), self.layer_sizes[0]);

        let net_data = Matrix::ones(data.rows(), 1).hcat(data);

        let mut z = net_data * self.get_net_weights(0);
        let mut a = self.criterion.activate(z.clone());

        for l in 1..self.layer_sizes.len() - 1 {
            let ones = Matrix::ones(a.rows(), 1);
            a = ones.hcat(&a);
            z = a * self.get_net_weights(l);
            a = self.criterion.activate(z.clone());
        }

        a
    }
}

impl<'a, T: Criterion> Optimizable for NeuralNet<'a, T> {
    type Data = Matrix<f64>;
	type Target = Matrix<f64>;

    /// Compute the gradient of the neural network.
    fn compute_grad(&self, params: &[f64], data: &Matrix<f64>, target: &Matrix<f64>) -> (f64, Vec<f64>) {
        self.compute_grad(params, data, target)
    }
}

impl<'a, T: Criterion> SupModel<Matrix<f64>, Matrix<f64>> for NeuralNet<'a, T> {
    /// Predict neural network output using forward propagation.
    fn predict(&self, data: &Matrix<f64>) -> Matrix<f64> {
        self.forward_prop(data)
    }

    /// Train the model using gradient optimization and back propagation.
    fn train(&mut self, data: &Matrix<f64>, values: &Matrix<f64>) {
        let start = self.weights.clone();
        let optimal_w = self.gd.optimize(self, &start[..], data, values);
        self.weights = optimal_w;
    }
}

pub trait Criterion {
    type ActFunc: ActivationFunc;
    type Cost: CostFunc<Matrix<f64>>;

    fn activate(&self, mat: Matrix<f64>) -> Matrix<f64> {
        mat.apply(&Self::ActFunc::func)
    }

    fn grad_activ(&self, mat: Matrix<f64>) -> Matrix<f64> {
        mat.apply(&Self::ActFunc::func_grad)
    }

    fn cost(&self, output: &Matrix<f64>, target: &Matrix<f64>) -> f64 {
        Self::Cost::cost(output, target)
    }

    fn cost_grad(&self, output: &Matrix<f64>, target: &Matrix<f64>) -> Matrix<f64> {
        Self::Cost::grad_cost(output, target)
    }
}

pub struct BCECriterion;

impl Criterion for BCECriterion {
    type ActFunc = activ_fn::Sigmoid;
    type Cost = cost_fn::CrossEntropyError;
}

pub struct MSECriterion;

impl Criterion for MSECriterion {
    type ActFunc = activ_fn::Linear;
    type Cost = cost_fn::MeanSqError;
}<|endoftext|>


<commit_before>//! The vector module.
//!
//! Currently contains all code
//! relating to the vector linear algebra struct.

use std::ops::{Mul, Add, Div, Sub, Index};
use libnum::{One, Zero, Float, FromPrimitive};
use std::cmp::PartialEq;
use linalg::Metric;
use linalg::utils;

/// The Vector struct.
///
/// Can be instantiated with any type.
pub struct Vector<T> {
	pub size: usize,
	pub data: Vec<T>
}

impl<T: Zero + One + Copy> Vector<T> {

    /// Constructor for Vector struct.
    ///
    /// Requires the vector data.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let vec = Vector::new(vec![1.0,2.0,3.0,4.0]);
    /// ```
    pub fn new(data: Vec<T>) -> Vector<T> {

    	let size = data.len();

        Vector {
            size: size,
            data: data
        }
    }

    /// Constructs Vector of all zeros.
    ///
    /// Requires the size of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let vec = Vector::<f64>::zeros(10);
    /// ```
    pub fn zeros(size: usize) -> Vector<T> {
    	Vector {
            size: size,
            data: vec![T::zero(); size]
        }
    }

    /// Constructs Vector of all ones.
    ///
    /// Requires the size of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let vec = Vector::<f64>::ones(10);
    /// ```
    pub fn ones(size: usize) -> Vector<T> {
    	Vector {
            size: size,
            data: vec![T::one(); size]
        }
    }
}

impl<T: Copy + One + Zero + Mul<T, Output=T> + Add<T, Output=T>> Vector<T> {

    /// Compute dot product with specified Vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::new(vec![1.0,2.0,3.0,4.0]);
    /// let b = Vector::new(vec![2.0; 4]);
    ///
    /// let c = a.dot(&b);
    /// assert_eq!(c, 20.0);
    /// ```
	pub fn dot(&self, v: &Vector<T>) -> T {
    	utils::dot(&self.data, &v.data)
    }
}

impl<T: Copy + Zero + Add<T, Output=T>> Vector<T> {

    /// The sum of the vector.
    ///
    /// Returns the sum of all elements in the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = a.sum();
    /// assert_eq!(c, 10.0);
    /// ```
    pub fn sum(&self) -> T {
        self.data.iter().fold(T::zero(), |sum, &val| sum + val)
    }
}

impl<T: Copy + Zero + Add<T, Output=T> + Div<T, Output=T> + FromPrimitive> Vector<T> {

    /// The mean of the vector.
    ///
    /// Returns the arithmetic mean of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::<f32>::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = a.mean();
    /// assert_eq!(c, 2.5);
    /// ```
    pub fn mean(&self) -> T {
        let sum = self.sum();
        sum / FromPrimitive::from_usize(self.data.len()).unwrap()
    }
}

/// Multiplies vector by scalar.
impl<T: Copy + One + Zero + Mul<T, Output=T>> Mul<T> for Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: T) -> Vector<T> {
        (&self) * (&f)
    }
}

/// Multiplies vector by scalar.
impl<'a, T: Copy + One + Zero + Mul<T, Output=T>> Mul<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: T) -> Vector<T> {
        self * (&f)
    }
}

/// Multiplies vector by scalar.
impl<'a, T: Copy + One + Zero + Mul<T, Output=T>> Mul<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: &T) -> Vector<T> {
        (&self) * f
    }
}

/// Multiplies vector by scalar.
impl<'a, 'b, T: Copy + One + Zero + Mul<T, Output=T>> Mul<&'b T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: &T) -> Vector<T> {
        let new_data = self.data.iter().map(|v| (*v) * (*f)).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Divides vector by scalar.
impl<T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<T> for Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: T) -> Vector<T> {
        (&self) / (&f)
    }
}

/// Divides vector by scalar.
impl<'a, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: T) -> Vector<T> {
        self / (&f)
    }
}

/// Divides vector by scalar.
impl<'a, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: &T) -> Vector<T> {
        (&self) / f
    }
}

/// Divides vector by scalar.
impl<'a, 'b, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<&'b T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: &T) -> Vector<T> {
    	assert!(*f != T::zero());
        let new_data = self.data.iter().map(|v| *v / *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Adds scalar to vector.
impl<T: Copy + One + Zero + Add<T, Output=T>> Add<T> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: T) -> Vector<T> {
        (&self) + (&f)
    }
}

/// Adds scalar to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: T) -> Vector<T> {
        self + (&f)
    }
}

/// Adds scalar to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: &T) -> Vector<T> {
        (&self) + f
    }
}

/// Adds scalar to vector.
impl<'a, 'b, T: Copy + One + Zero + Add<T, Output=T>> Add<&'b T> for &'a Vector<T> {
	type Output = Vector<T>;

	fn add(self, f: &T) -> Vector<T> {
		let new_data = self.data.iter().map(|v| *v + *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Adds vector to vector.
impl<T: Copy + One + Zero + Add<T, Output=T>> Add<Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: Vector<T>) -> Vector<T> {
        (&self) + (&v)
    }
}

/// Adds vector to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<Vector<T>> for &'a Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: Vector<T>) -> Vector<T> {
        self + (&v)
    }
}

/// Adds vector to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<&'a Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: &Vector<T>) -> Vector<T> {
        (&self) + v
    }
}

/// Adds vector to vector.
impl<'a, 'b, T: Copy + One + Zero + Add<T, Output=T>> Add<&'b Vector<T>> for &'a Vector<T> {
	type Output = Vector<T>;

	fn add(self, v: &Vector<T>) -> Vector<T> {
		assert!(self.size == v.size);

		let new_data = utils::vec_sum(&self.data, &v.data);

        Vector {
            size: self.size,
            data: new_data
        }
	}
}

/// Subtracts scalar from vector.
impl<T: Copy + One + Zero + Sub<T, Output=T>> Sub<T> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: T) -> Vector<T> {
        (&self) - (&f)
    }
}

/// Subtracts scalar from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: T) -> Vector<T> {
        self - (&f)
    }
}

/// Subtracts scalar from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: &T) -> Vector<T> {
            (&self) - f
        }
    }

/// Subtracts scalar from vector.
impl<'a, 'b, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'b T> for &'a Vector<T> {
	type Output = Vector<T>;

	fn sub(self, f: &T) -> Vector<T> {
		let new_data = self.data.iter().map(|v| *v - *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Subtracts vector from vector.
impl<T: Copy + One + Zero + Sub<T, Output=T>> Sub<Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: Vector<T>) -> Vector<T> {
        (&self) - (&v)
    }
}

/// Subtracts vector from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<Vector<T>> for &'a Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: Vector<T>) -> Vector<T> {
        self - (&v)
    }
}

/// Subtracts vector from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'a Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: &Vector<T>) -> Vector<T> {
        (&self) - v
    }
}

/// Subtracts vector from vector.
impl<'a, 'b, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'b Vector<T>> for &'a Vector<T> {
	type Output = Vector<T>;

	fn sub(self, v: &Vector<T>) -> Vector<T> {
		assert!(self.size == v.size);

		let new_data = utils::vec_sub(&self.data, &v.data);

        Vector {
            size: self.size,
            data: new_data
        }
	}
}

/// Indexes vector.
impl<T> Index<usize> for Vector<T> {
	type Output = T;

	fn index(&self, idx : usize) -> &T {
		assert!(idx < self.size);

		&self.data[idx]
	}
}

impl<T: Float> Metric<T> for Vector<T> {

    /// Compute euclidean norm for vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    /// use rusty_machine::linalg::Metric;
    ///
    /// let a = Vector::new(vec![3.0,4.0]);
    /// let c = a.norm();
    ///
    /// assert_eq!(c, 5.0);
    /// ```
    fn norm(&self) -> T {
        let mut s = T::zero();

        for u in &self.data {
            s = s + (*u) * (*u);
        }

        s.sqrt()
    }
}<commit_msg>Implemented variance for vector.<commit_after>//! The vector module.
//!
//! Currently contains all code
//! relating to the vector linear algebra struct.

use std::ops::{Mul, Add, Div, Sub, Index};
use libnum::{One, Zero, Float, FromPrimitive};
use std::cmp::PartialEq;
use linalg::Metric;
use linalg::utils;

/// The Vector struct.
///
/// Can be instantiated with any type.
pub struct Vector<T> {
	pub size: usize,
	pub data: Vec<T>
}

impl<T: Zero + One + Copy> Vector<T> {

    /// Constructor for Vector struct.
    ///
    /// Requires the vector data.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let vec = Vector::new(vec![1.0,2.0,3.0,4.0]);
    /// ```
    pub fn new(data: Vec<T>) -> Vector<T> {

    	let size = data.len();

        Vector {
            size: size,
            data: data
        }
    }

    /// Constructs Vector of all zeros.
    ///
    /// Requires the size of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let vec = Vector::<f64>::zeros(10);
    /// ```
    pub fn zeros(size: usize) -> Vector<T> {
    	Vector {
            size: size,
            data: vec![T::zero(); size]
        }
    }

    /// Constructs Vector of all ones.
    ///
    /// Requires the size of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let vec = Vector::<f64>::ones(10);
    /// ```
    pub fn ones(size: usize) -> Vector<T> {
    	Vector {
            size: size,
            data: vec![T::one(); size]
        }
    }
}

impl<T: Copy + One + Zero + Mul<T, Output=T> + Add<T, Output=T>> Vector<T> {

    /// Compute dot product with specified Vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::new(vec![1.0,2.0,3.0,4.0]);
    /// let b = Vector::new(vec![2.0; 4]);
    ///
    /// let c = a.dot(&b);
    /// assert_eq!(c, 20.0);
    /// ```
	pub fn dot(&self, v: &Vector<T>) -> T {
    	utils::dot(&self.data, &v.data)
    }
}

impl<T: Copy + Zero + Add<T, Output=T>> Vector<T> {

    /// The sum of the vector.
    ///
    /// Returns the sum of all elements in the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = a.sum();
    /// assert_eq!(c, 10.0);
    /// ```
    pub fn sum(&self) -> T {
        self.data.iter().fold(T::zero(), |sum, &val| sum + val)
    }
}

impl<T: Copy + Zero + Float + FromPrimitive> Vector<T> {

    /// The mean of the vector.
    ///
    /// Returns the arithmetic mean of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::<f32>::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = a.mean();
    /// assert_eq!(c, 2.5);
    /// ```
    pub fn mean(&self) -> T {
        let sum = self.sum();
        sum / FromPrimitive::from_usize(self.data.len()).unwrap()
    }

    /// The variance of the vector.
    ///
    /// Returns the unbiased sample variance of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::<f32>::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = a.variance();
    /// assert_eq!(c, 5.0/3.0);
    /// ```
    pub fn variance(&self) -> T {
        let m = self.mean();
        let mut var = T::zero();

        for u in &self.data {
            var = var + (*u-m)*(*u-m);
        }

        var / FromPrimitive::from_usize(self.data.len() - 1).unwrap()
    }
}

/// Multiplies vector by scalar.
impl<T: Copy + One + Zero + Mul<T, Output=T>> Mul<T> for Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: T) -> Vector<T> {
        (&self) * (&f)
    }
}

/// Multiplies vector by scalar.
impl<'a, T: Copy + One + Zero + Mul<T, Output=T>> Mul<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: T) -> Vector<T> {
        self * (&f)
    }
}

/// Multiplies vector by scalar.
impl<'a, T: Copy + One + Zero + Mul<T, Output=T>> Mul<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: &T) -> Vector<T> {
        (&self) * f
    }
}

/// Multiplies vector by scalar.
impl<'a, 'b, T: Copy + One + Zero + Mul<T, Output=T>> Mul<&'b T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: &T) -> Vector<T> {
        let new_data = self.data.iter().map(|v| (*v) * (*f)).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Divides vector by scalar.
impl<T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<T> for Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: T) -> Vector<T> {
        (&self) / (&f)
    }
}

/// Divides vector by scalar.
impl<'a, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: T) -> Vector<T> {
        self / (&f)
    }
}

/// Divides vector by scalar.
impl<'a, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: &T) -> Vector<T> {
        (&self) / f
    }
}

/// Divides vector by scalar.
impl<'a, 'b, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<&'b T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: &T) -> Vector<T> {
    	assert!(*f != T::zero());
        let new_data = self.data.iter().map(|v| *v / *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Adds scalar to vector.
impl<T: Copy + One + Zero + Add<T, Output=T>> Add<T> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: T) -> Vector<T> {
        (&self) + (&f)
    }
}

/// Adds scalar to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: T) -> Vector<T> {
        self + (&f)
    }
}

/// Adds scalar to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: &T) -> Vector<T> {
        (&self) + f
    }
}

/// Adds scalar to vector.
impl<'a, 'b, T: Copy + One + Zero + Add<T, Output=T>> Add<&'b T> for &'a Vector<T> {
	type Output = Vector<T>;

	fn add(self, f: &T) -> Vector<T> {
		let new_data = self.data.iter().map(|v| *v + *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Adds vector to vector.
impl<T: Copy + One + Zero + Add<T, Output=T>> Add<Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: Vector<T>) -> Vector<T> {
        (&self) + (&v)
    }
}

/// Adds vector to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<Vector<T>> for &'a Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: Vector<T>) -> Vector<T> {
        self + (&v)
    }
}

/// Adds vector to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<&'a Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: &Vector<T>) -> Vector<T> {
        (&self) + v
    }
}

/// Adds vector to vector.
impl<'a, 'b, T: Copy + One + Zero + Add<T, Output=T>> Add<&'b Vector<T>> for &'a Vector<T> {
	type Output = Vector<T>;

	fn add(self, v: &Vector<T>) -> Vector<T> {
		assert!(self.size == v.size);

		let new_data = utils::vec_sum(&self.data, &v.data);

        Vector {
            size: self.size,
            data: new_data
        }
	}
}

/// Subtracts scalar from vector.
impl<T: Copy + One + Zero + Sub<T, Output=T>> Sub<T> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: T) -> Vector<T> {
        (&self) - (&f)
    }
}

/// Subtracts scalar from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: T) -> Vector<T> {
        self - (&f)
    }
}

/// Subtracts scalar from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: &T) -> Vector<T> {
            (&self) - f
        }
    }

/// Subtracts scalar from vector.
impl<'a, 'b, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'b T> for &'a Vector<T> {
	type Output = Vector<T>;

	fn sub(self, f: &T) -> Vector<T> {
		let new_data = self.data.iter().map(|v| *v - *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Subtracts vector from vector.
impl<T: Copy + One + Zero + Sub<T, Output=T>> Sub<Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: Vector<T>) -> Vector<T> {
        (&self) - (&v)
    }
}

/// Subtracts vector from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<Vector<T>> for &'a Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: Vector<T>) -> Vector<T> {
        self - (&v)
    }
}

/// Subtracts vector from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'a Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: &Vector<T>) -> Vector<T> {
        (&self) - v
    }
}

/// Subtracts vector from vector.
impl<'a, 'b, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'b Vector<T>> for &'a Vector<T> {
	type Output = Vector<T>;

	fn sub(self, v: &Vector<T>) -> Vector<T> {
		assert!(self.size == v.size);

		let new_data = utils::vec_sub(&self.data, &v.data);

        Vector {
            size: self.size,
            data: new_data
        }
	}
}

/// Indexes vector.
impl<T> Index<usize> for Vector<T> {
	type Output = T;

	fn index(&self, idx : usize) -> &T {
		assert!(idx < self.size);

		&self.data[idx]
	}
}

impl<T: Float> Metric<T> for Vector<T> {

    /// Compute euclidean norm for vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    /// use rusty_machine::linalg::Metric;
    ///
    /// let a = Vector::new(vec![3.0,4.0]);
    /// let c = a.norm();
    ///
    /// assert_eq!(c, 5.0);
    /// ```
    fn norm(&self) -> T {
        let mut s = T::zero();

        for u in &self.data {
            s = s + (*u) * (*u);
        }

        s.sqrt()
    }
}<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//xfail-test

// Currently failing with an ICE in trans.  (FIXME: #2794)

trait Cat {
    fn meow() -> bool;
    fn scratch() -> bool { self.purr() }
    fn purr() -> bool { true }
}

impl Cat for int {
    fn meow() -> bool {
        self.scratch()
    }
}

pub fn main() {
    assert!(5.meow());
}
<commit_msg>auto merge of #6321 : ILyoan/rust/test4350, r=z0w0<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//xfail-test

// Currently failing with an ICE in trans.  (FIXME: #4350)

trait Cat {
    fn meow(&self) -> bool;
    fn scratch(&self) -> bool { self.purr() }
    fn purr(&self) -> bool { true }
}

impl Cat for int {
    fn meow(&self) -> bool {
        self.scratch()
    }
}

pub fn main() {
    assert!(5.meow());
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

Dynamic library facilities.

A simple wrapper over the platforms dynamic library facilities

*/
use c_str::ToCStr;
use cast;
use path;
use libc;
use ops::*;
use option::*;
use result::*;

pub struct DynamicLibrary { priv handle: *libc::c_void }

impl Drop for DynamicLibrary {
    fn drop(&self) {
        match do dl::check_for_errors_in {
            unsafe {
                dl::close(self.handle)
            }
        } {
            Ok(()) => {},
            Err(str) => fail!(str)
        }
    }
}

impl DynamicLibrary {
    /// Lazily open a dynamic library. When passed None it gives a
    /// handle to the calling process
    pub fn open(filename: Option<&path::Path>) -> Result<DynamicLibrary, ~str> {
        unsafe {
            let maybe_library = do dl::check_for_errors_in {
                match filename {
                    Some(name) => dl::open_external(name),
                    None => dl::open_internal()
                }
            };

            // The dynamic library must not be constructed if there is
            // an error opening the library so the destructor does not
            // run.
            match maybe_library {
                Err(err) => Err(err),
                Ok(handle) => Ok(DynamicLibrary { handle: handle })
            }
        }
    }

    /// Access the value at the symbol of the dynamic library
    pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, ~str> {
        // This function should have a lifetime constraint of 'self on
        // T but that feature is still unimplemented

        let maybe_symbol_value = do dl::check_for_errors_in {
            do symbol.with_c_str |raw_string| {
                dl::symbol(self.handle, raw_string)
            }
        };

        // The value must not be constructed if there is an error so
        // the destructor does not run.
        match maybe_symbol_value {
            Err(err) => Err(err),
            Ok(symbol_value) => Ok(cast::transmute(symbol_value))
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use option::*;
    use result::*;
    use path::*;
    use libc;

    #[test]
    #[ignore(cfg(windows))] // FIXME #8818
    fn test_loading_cosine() {
        // The math library does not need to be loaded since it is already
        // statically linked in
        let libm = match DynamicLibrary::open(None) {
            Err(error) => fail!("Could not load self as module: %s", error),
            Ok(libm) => libm
        };

        // Unfortunately due to issue #6194 it is not possible to call
        // this as a C function
        let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
            match libm.symbol("cos") {
                Err(error) => fail!("Could not load function cos: %s", error),
                Ok(cosine) => cosine
            }
        };

        let argument = 0.0;
        let expected_result = 1.0;
        let result = cosine(argument);
        if result != expected_result {
            fail!("cos(%?) != %? but equaled %? instead", argument,
                  expected_result, result)
        }
    }

    #[test]
    #[cfg(target_os = "linux")]
    #[cfg(target_os = "macos")]
    #[cfg(target_os = "freebsd")]
    fn test_errors_do_not_crash() {
        // Open /dev/null as a library to get an error, and make sure
        // that only causes an error, and not a crash.
        let path = GenericPath::from_str("/dev/null");
        match DynamicLibrary::open(Some(&path)) {
            Err(_) => {}
            Ok(_) => fail!("Successfully opened the empty library.")
        }
    }
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
mod dl {
    use c_str::ToCStr;
    use libc;
    use path;
    use ptr;
    use str;
    use unstable::sync::atomically;
    use result::*;

    pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
        #[fixed_stack_segment]; #[inline(never)];
        do filename.with_c_str |raw_name| {
            dlopen(raw_name, Lazy as libc::c_int)
        }
    }

    pub unsafe fn open_internal() -> *libc::c_void {
        #[fixed_stack_segment]; #[inline(never)];

        dlopen(ptr::null(), Lazy as libc::c_int)
    }

    pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> {
        #[fixed_stack_segment]; #[inline(never)];

        unsafe {
            do atomically {
                let _old_error = dlerror();

                let result = f();

                let last_error = dlerror();
                if ptr::null() == last_error {
                    Ok(result)
                } else {
                    Err(str::raw::from_c_str(last_error))
                }
            }
        }
    }

    pub unsafe fn symbol(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void {
        #[fixed_stack_segment]; #[inline(never)];

        dlsym(handle, symbol)
    }
    pub unsafe fn close(handle: *libc::c_void) {
        #[fixed_stack_segment]; #[inline(never)];

        dlclose(handle); ()
    }

    pub enum RTLD {
        Lazy = 1,
        Now = 2,
        Global = 256,
        Local = 0,
    }

    #[link_name = "dl"]
    extern {
        fn dlopen(filename: *libc::c_char, flag: libc::c_int) -> *libc::c_void;
        fn dlerror() -> *libc::c_char;
        fn dlsym(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void;
        fn dlclose(handle: *libc::c_void) -> libc::c_int;
    }
}

#[cfg(target_os = "win32")]
mod dl {
    use os;
    use libc;
    use path;
    use ptr;
    use unstable::sync::atomically;
    use result::*;

    pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
        #[fixed_stack_segment]; #[inline(never)];
        do os::win32::as_utf16_p(filename.to_str()) |raw_name| {
            LoadLibraryW(raw_name)
        }
    }

    pub unsafe fn open_internal() -> *libc::c_void {
        #[fixed_stack_segment]; #[inline(never)];
        let handle = ptr::null();
        GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
        handle
    }

    pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> {
        #[fixed_stack_segment]; #[inline(never)];
        unsafe {
            do atomically {
                SetLastError(0);

                let result = f();

                let error = os::errno();
                if 0 == error {
                    Ok(result)
                } else {
                    Err(fmt!("Error code %?", error))
                }
            }
        }
    }
    pub unsafe fn symbol(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void {
        #[fixed_stack_segment]; #[inline(never)];
        GetProcAddress(handle, symbol)
    }
    pub unsafe fn close(handle: *libc::c_void) {
        #[fixed_stack_segment]; #[inline(never)];
        FreeLibrary(handle); ()
    }

    #[cfg(target_arch = "x86")]
    #[link_name = "kernel32"]
    extern "stdcall" {
        fn SetLastError(error: u32);
        fn LoadLibraryW(name: *u16) -> *libc::c_void;
        fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
                              handle: **libc::c_void) -> *libc::c_void;
        fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
        fn FreeLibrary(handle: *libc::c_void);
    }

    #[cfg(target_arch = "x86_64")]
    #[link_name = "kernel32"]
    extern {
        fn SetLastError(error: u32);
        fn LoadLibraryW(name: *u16) -> *libc::c_void;
        fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
                              handle: **libc::c_void) -> *libc::c_void;
        fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
        fn FreeLibrary(handle: *libc::c_void);
    }
}
<commit_msg>auto merge of #9138 : alexcrichton/rust/dynamic-lib-not-threadsafe, r=thestinger<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

Dynamic library facilities.

A simple wrapper over the platforms dynamic library facilities

*/
use c_str::ToCStr;
use cast;
use path;
use libc;
use ops::*;
use option::*;
use result::*;

pub struct DynamicLibrary { priv handle: *libc::c_void }

impl Drop for DynamicLibrary {
    fn drop(&self) {
        match do dl::check_for_errors_in {
            unsafe {
                dl::close(self.handle)
            }
        } {
            Ok(()) => {},
            Err(str) => fail!(str)
        }
    }
}

impl DynamicLibrary {
    /// Lazily open a dynamic library. When passed None it gives a
    /// handle to the calling process
    pub fn open(filename: Option<&path::Path>) -> Result<DynamicLibrary, ~str> {
        unsafe {
            let maybe_library = do dl::check_for_errors_in {
                match filename {
                    Some(name) => dl::open_external(name),
                    None => dl::open_internal()
                }
            };

            // The dynamic library must not be constructed if there is
            // an error opening the library so the destructor does not
            // run.
            match maybe_library {
                Err(err) => Err(err),
                Ok(handle) => Ok(DynamicLibrary { handle: handle })
            }
        }
    }

    /// Access the value at the symbol of the dynamic library
    pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, ~str> {
        // This function should have a lifetime constraint of 'self on
        // T but that feature is still unimplemented

        let maybe_symbol_value = do dl::check_for_errors_in {
            do symbol.with_c_str |raw_string| {
                dl::symbol(self.handle, raw_string)
            }
        };

        // The value must not be constructed if there is an error so
        // the destructor does not run.
        match maybe_symbol_value {
            Err(err) => Err(err),
            Ok(symbol_value) => Ok(cast::transmute(symbol_value))
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use option::*;
    use result::*;
    use path::*;
    use libc;

    #[test]
    // #[ignore(cfg(windows))] // FIXME #8818
    #[ignore] // FIXME #9137 this library isn't thread-safe
    fn test_loading_cosine() {
        // The math library does not need to be loaded since it is already
        // statically linked in
        let libm = match DynamicLibrary::open(None) {
            Err(error) => fail!("Could not load self as module: %s", error),
            Ok(libm) => libm
        };

        // Unfortunately due to issue #6194 it is not possible to call
        // this as a C function
        let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
            match libm.symbol("cos") {
                Err(error) => fail!("Could not load function cos: %s", error),
                Ok(cosine) => cosine
            }
        };

        let argument = 0.0;
        let expected_result = 1.0;
        let result = cosine(argument);
        if result != expected_result {
            fail!("cos(%?) != %? but equaled %? instead", argument,
                  expected_result, result)
        }
    }

    #[test]
    #[cfg(target_os = "linux")]
    #[cfg(target_os = "macos")]
    #[cfg(target_os = "freebsd")]
    #[ignore] // FIXME #9137 this library isn't thread-safe
    fn test_errors_do_not_crash() {
        // Open /dev/null as a library to get an error, and make sure
        // that only causes an error, and not a crash.
        let path = GenericPath::from_str("/dev/null");
        match DynamicLibrary::open(Some(&path)) {
            Err(_) => {}
            Ok(_) => fail!("Successfully opened the empty library.")
        }
    }
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
mod dl {
    use c_str::ToCStr;
    use libc;
    use path;
    use ptr;
    use str;
    use unstable::sync::atomically;
    use result::*;

    pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
        #[fixed_stack_segment]; #[inline(never)];
        do filename.with_c_str |raw_name| {
            dlopen(raw_name, Lazy as libc::c_int)
        }
    }

    pub unsafe fn open_internal() -> *libc::c_void {
        #[fixed_stack_segment]; #[inline(never)];

        dlopen(ptr::null(), Lazy as libc::c_int)
    }

    pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> {
        #[fixed_stack_segment]; #[inline(never)];

        unsafe {
            do atomically {
                let _old_error = dlerror();

                let result = f();

                let last_error = dlerror();
                if ptr::null() == last_error {
                    Ok(result)
                } else {
                    Err(str::raw::from_c_str(last_error))
                }
            }
        }
    }

    pub unsafe fn symbol(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void {
        #[fixed_stack_segment]; #[inline(never)];

        dlsym(handle, symbol)
    }
    pub unsafe fn close(handle: *libc::c_void) {
        #[fixed_stack_segment]; #[inline(never)];

        dlclose(handle); ()
    }

    pub enum RTLD {
        Lazy = 1,
        Now = 2,
        Global = 256,
        Local = 0,
    }

    #[link_name = "dl"]
    extern {
        fn dlopen(filename: *libc::c_char, flag: libc::c_int) -> *libc::c_void;
        fn dlerror() -> *libc::c_char;
        fn dlsym(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void;
        fn dlclose(handle: *libc::c_void) -> libc::c_int;
    }
}

#[cfg(target_os = "win32")]
mod dl {
    use os;
    use libc;
    use path;
    use ptr;
    use unstable::sync::atomically;
    use result::*;

    pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
        #[fixed_stack_segment]; #[inline(never)];
        do os::win32::as_utf16_p(filename.to_str()) |raw_name| {
            LoadLibraryW(raw_name)
        }
    }

    pub unsafe fn open_internal() -> *libc::c_void {
        #[fixed_stack_segment]; #[inline(never)];
        let handle = ptr::null();
        GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
        handle
    }

    pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> {
        #[fixed_stack_segment]; #[inline(never)];
        unsafe {
            do atomically {
                SetLastError(0);

                let result = f();

                let error = os::errno();
                if 0 == error {
                    Ok(result)
                } else {
                    Err(fmt!("Error code %?", error))
                }
            }
        }
    }
    pub unsafe fn symbol(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void {
        #[fixed_stack_segment]; #[inline(never)];
        GetProcAddress(handle, symbol)
    }
    pub unsafe fn close(handle: *libc::c_void) {
        #[fixed_stack_segment]; #[inline(never)];
        FreeLibrary(handle); ()
    }

    #[cfg(target_arch = "x86")]
    #[link_name = "kernel32"]
    extern "stdcall" {
        fn SetLastError(error: u32);
        fn LoadLibraryW(name: *u16) -> *libc::c_void;
        fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
                              handle: **libc::c_void) -> *libc::c_void;
        fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
        fn FreeLibrary(handle: *libc::c_void);
    }

    #[cfg(target_arch = "x86_64")]
    #[link_name = "kernel32"]
    extern {
        fn SetLastError(error: u32);
        fn LoadLibraryW(name: *u16) -> *libc::c_void;
        fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
                              handle: **libc::c_void) -> *libc::c_void;
        fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
        fn FreeLibrary(handle: *libc::c_void);
    }
}
<|endoftext|>