<commit_before>use std::mem;
use std::ptr;
use std::ops;
use std::cmp;
use std::fmt;
use std::num::One;
use std::iter::Iterator;
use std::rt::heap::{allocate, deallocate};
use std::raw::Slice as RawSlice;

// The following is needed for destroying matrix.

#[doc = "
Represents a matrix of numbers.

The numbers are stored in column-major order.
This is the standard in Fortran and MATLAB.

Currently, the stride is same as the number
of rows. May be changed later on.

For a row vector, the stride  = 1.

"]
pub struct Mat<T:Ord+Copy> {
    rows : uint,
    cols : uint,
    ptr : *mut T
}

/// A matrix of 64-bit signed integers
pub type MatI64 = Mat<i64>;
/// A matrix of 64-bit floating point numbers.
pub type MatF64 = Mat<f64>;

/// Errors related to matrix operations
#[deriving(Show)]
pub enum MatErr{
    //EmptyMatrix,
    DimensionsMismatch,
}

/// Static functions for creating  a matrix
impl<T:Num+Ord+Copy> Mat<T> {

    pub fn new(rows: uint, cols : uint)-> Mat<T> {
        assert! (mem::size_of::<T>() != 0);
        let size = rows * cols;
        let bytes = size * mem::size_of::<T>();
        let raw = unsafe {
            allocate(bytes, mem::min_align_of::<T>())
        };
        let ptr = raw as *mut T;
        Mat { rows : rows, cols : cols, ptr : ptr}
    }

    /// Constructs a matrix of all zeros
    pub fn zeros(rows: uint, cols : uint)-> Mat<T> {
        let m : Mat<T> = Mat::new(rows, cols);
        // zero out the memory
        unsafe { ptr::zero_memory(m.ptr, m.capacity())};
        m
    }

    pub fn ones(rows: uint, cols : uint)-> Mat<T> {
        let m : Mat<T> = Mat::new(rows, cols);
        // fill with ones
        let ptr = m.ptr;
        let o : T = One::one();
        unsafe {
            for c in range(0, cols){
                for r in range (0, rows){
                    let offset = m.cell_to_offset(r, c);
                    let p  = ptr.offset(offset as int);
                    *p = o;
                }
            }
        }
        m
    }

    pub fn from_slice(rows: uint, cols : uint, values: &[T]) -> Mat<T>{
        let mut mat : Mat<T> = Mat::new(rows, cols);
        let n_cells = mat.num_cells();
        let stride = mat.stride();
        // get a mutable slice from m
        {
            let dst_slice = mat.as_mut_slice();
            let n_values = values.len();
            // The number of entries we can copy
            let n_fill = cmp::min(n_values, n_cells);
            let mut n = 0;
            let mut offset_src = 0;
            let mut offset_dst = 0;
            for _ in range(0, cols){
                for r in range(0, rows){
                    n+=1;
                    dst_slice[offset_dst + r] = values[offset_src + r];
                    if n == n_fill {
                        break;
                    }
                }
                if n == n_fill {
                    break;
                }
                offset_src += rows;
                offset_dst += stride;
            }
        }
        // return
        mat
    }

    pub fn from_iter< A : Iterator<T>>(rows: uint, cols : uint, mut iter: A) -> Mat<T>{
        let mut mat : Mat<T> = Mat::new(rows, cols);
        let stride = mat.stride();
        // get a mutable slice from m
        {
            let dst_slice = mat.as_mut_slice();
            let mut offset_dst = 0;
            'outer: for _ in range(0, cols){
                for r in range(0, rows){
                    let next_val = iter.next();
                    match next_val{
                        Some(val) => dst_slice[offset_dst + r] = val,
                        None => break 'outer
                    };
                }
                offset_dst += stride;
            }
        }
        // return
        mat
    }
}

/// Main methods of a matrix
impl<T:Num+Ord+Copy> Mat<T> {
    pub fn num_rows(&self) -> uint {
        self.rows
    }

    pub fn num_cols(&self) -> uint {
        self.cols
    }

    pub fn size (&self)-> (uint, uint){
        (self.rows, self.cols)
    }
    pub fn num_cells(&self)->uint {
        self.rows * self.cols
    }
    /// Returns the number of actual memory elements
    /// per column stored in the memory
    pub fn stride (&self)->uint {
        self.rows
    }

    pub fn capacity(&self)-> uint {
        self.stride() * self.cols
    }

    /// Returns an unsafe pointer to the matrix's
    /// buffer.
    #[inline]
    pub fn as_ptr(&self)-> *const T{
        self.ptr as *const T
    }

    /// Returns a mutable unsafe pointer to
    /// the matrix's underlying buffer
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut T{
        self.ptr
    }

    #[inline]
    pub fn get(&self, r : uint, c : uint) -> T  {
        unsafe {
            *self.ptr.offset(self.cell_to_offset(r, c) as int)
        }
    }

    /// Converts an index to cell address (row, column)
    #[inline]
    pub fn index_to_cell(&self, index : uint) -> (uint, uint){
        let c = index / self.rows;
        let r = index - c*self.rows;
        (r, c)
    }

    /// Converts a cell address to an index (r, c) to index
    #[inline]
    pub fn cell_to_index(&self, r : uint,  c: uint) -> uint{
        c * self.rows + r
    }

    /// Converts the matrix to vector from standard library
    pub fn to_std_vec(&self) -> Vec<T> {
        let mut vec: Vec<T> = Vec::with_capacity(self.num_cells());
        // We iterate over elements in matrix and push in the vector
        let s = self.as_slice_();
        for c in range(0, self.cols){
            for r in range (0, self.rows){
                let offset = self.cell_to_offset(r, c);
                vec.push(s[offset]);
            }
        }
        vec
    }
}

impl<T:Num+Ord+Copy> Index<uint,T> for Mat<T> {
    #[inline]
    fn index<'a>(&'a self, index: &uint) -> &'a T {
        // The matrix is column major order
        let (r, c) = self.index_to_cell(*index);
        let offset = c * self.stride() + r;
        unsafe {
            &*self.ptr.offset(offset as int)
        }
    }
}

impl<T:Num+Ord+Copy> Mat<T>{
    /// This function is for internal use only.
    #[inline]
    fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        unsafe {
            mem::transmute(RawSlice {
                data: self.as_mut_ptr() as *const T,
                len: self.capacity(),
            })
        }
    }
}

impl <T:Num+Ord+Copy> Clone for Mat<T> {

    fn clone(&self )-> Mat<T> {
        let m : Mat<T> = Mat::new(self.rows, self.cols);
        unsafe{
            ptr::copy_memory(m.ptr, self.ptr as *const T, self.capacity());
        }
        m
    }
}

impl <T:Num+Ord+Copy+fmt::Show> fmt::Show for Mat<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = self.as_slice_();
        try!(write!(f, "["));
        // Here we print row by row
        for r in range (0, self.rows) {
           try!(write!(f, "\n  "));
            for c in range (0, self.cols){
                let offset = c * self.stride() + r;
                try!(write!(f, "{} ", s[offset]));
            }
        }
        try!(write!(f, "\n]\n"));
        Ok(())
    }
}

/// Matrix addition support
impl<T:Num+Ord+Copy> ops::Add<Mat<T>, Mat<T>> for Mat<T> {
    fn add(&self, _rhs: &Mat<T>) -> Mat<T> {
        // Validate dimensions are same.
        if self.size() != _rhs.size(){
            fail!(DimensionsMismatch.to_string());
        }
        let result : Mat<T> = Mat::new(self.rows, self.cols);
        let pa = self.ptr;
        let pb = _rhs.ptr;
        let pc = result.ptr;
        let n = self.capacity();
        unsafe{
            for i_ in range(0, n){
                let i = i_ as int;
                *pc.offset(i) = *pa.offset(i) + *pb.offset(i);
            }
        }
        result
    }
}

#[unsafe_destructor]
impl<T:Num+Ord+Copy> Drop for Mat<T> {
    fn drop(&mut self) {
        if self.num_cells() != 0 {
            unsafe {
                dealloc(self.ptr, self.capacity())
            }
        }
    }
}

/******************************************************
 *
 *   Private implementation of Mat
 *
 *******************************************************/

impl<T:Num+Ord+Copy> Mat<T> {
    /// Returns a slice into `self`.
    #[inline]
    fn as_slice_<'a>(&'a self) -> &'a [T] {
        unsafe { mem::transmute(RawSlice { data: self.as_ptr(), len: self.capacity() }) }
    }

    /// Maps a cell index to actual offset in the internal buffer
    #[inline]
    fn cell_to_offset(&self, r : uint,  c: uint)-> uint {
        c * self.stride() + r
    }
}

/***
Private helper functions follow
*/

#[inline]
unsafe fn dealloc<T>(ptr: *mut T, len: uint) {
    if mem::size_of::<T>() != 0 {
        deallocate(ptr as *mut u8,
                   len * mem::size_of::<T>(),
                   mem::min_align_of::<T>())
    }
}

/******************************************************
 *
 *   Unit tests follow.
 *
 *******************************************************/

#[cfg(test)]
mod tests {

    use  super::{Mat, MatI64};

    #[test]
    fn  create_mat0(){
        let m : MatI64 = Mat::new(3, 4);
        assert_eq!(m.num_cells(), 12);
        assert_eq!(m.size(), (3, 4));
        let v : i64 = m.get(0, 0);
        assert_eq!(v, 0i64);
    }

    #[test]
    fn test_from_iter0(){
        let m : MatI64 = Mat::from_iter(4, 4, range(1, 20));
        let b: Vec<i64> = range(1, 17).collect();
        assert!(m.as_slice_() == b.as_slice_());
        let m : MatI64 = Mat::from_iter(4, 4, range(1, 16));
        assert_eq!(m.get(0, 0), 1);
        assert_eq!(m.get(2, 2), 11);
        let mut b: Vec<i64> = range(1, 16).collect();
        b.push(0);
        assert!(m.as_slice_() == b.as_slice_());
    }

    #[test]
    fn test_index0(){
        let m : MatI64 = Mat::from_iter(4, 4, range(1, 20));
        let x = m[4];
        assert_eq!(x, 5);
    }

    #[test]
    fn test_cell_index_mapping(){
        let rows = 20;
        let cols = 10;
        let m : MatI64 = Mat::new(rows, cols);
        assert_eq!(m.index_to_cell(3 + 2*rows), (3, 2));
        assert_eq!(m.cell_to_index(3, 2), 3 + 2*rows);
        assert_eq!(m.cell_to_index(5, 7), 145);
        assert_eq!(m.index_to_cell(145), (5, 7));
    }

    #[test]
    fn test_to_std_vec(){
        let m : MatI64 = Mat::from_iter(4, 3, range(0, 12));
        let v1 = m.to_std_vec();
        let v2 : Vec<i64> = range(0, 12).collect();
        assert_eq!(v1, v2);
    }

    #[test]
    fn test_ones(){
        let m : MatI64 = Mat::ones(4, 2);
        let v = vec![1i64, 1, 1, 1, 1, 1, 1, 1];
        assert_eq!(m.to_std_vec(), v);
    }

    #[test]
    fn test_sum(){
        let m : MatI64 = Mat::ones(4, 2);
        let m2 = m  + m;
        let v = vec![2i64, 2, 2, 2, 2, 2, 2, 2];
        assert_eq!(m2.to_std_vec(), v);
    }

    #[test]
    #[should_fail]
    fn test_sum_fail(){
        let m1 : MatI64 = Mat::ones(4, 2);
        let m2 : MatI64 = Mat::ones(3, 2);
        m1 + m2;
    }

}
<commit_msg>Subtraction.<commit_after>use std::mem;
use std::ptr;
use std::ops;
use std::cmp;
use std::fmt;
use std::num::One;
use std::iter::Iterator;
use std::rt::heap::{allocate, deallocate};
use std::raw::Slice as RawSlice;

// The following is needed for destroying matrix.

#[doc = "
Represents a matrix of numbers.

The numbers are stored in column-major order.
This is the standard in Fortran and MATLAB.

Currently, the stride is same as the number
of rows. May be changed later on.

For a row vector, the stride  = 1.

"]
pub struct Mat<T:Ord+Copy> {
    rows : uint,
    cols : uint,
    ptr : *mut T
}

/// A matrix of 64-bit signed integers
pub type MatI64 = Mat<i64>;
/// A matrix of 64-bit floating point numbers.
pub type MatF64 = Mat<f64>;

/// Errors related to matrix operations
#[deriving(Show)]
pub enum MatErr{
    //EmptyMatrix,
    DimensionsMismatch,
}

/// Static functions for creating  a matrix
impl<T:Num+Ord+Copy> Mat<T> {

    pub fn new(rows: uint, cols : uint)-> Mat<T> {
        assert! (mem::size_of::<T>() != 0);
        let size = rows * cols;
        let bytes = size * mem::size_of::<T>();
        let raw = unsafe {
            allocate(bytes, mem::min_align_of::<T>())
        };
        let ptr = raw as *mut T;
        Mat { rows : rows, cols : cols, ptr : ptr}
    }

    /// Constructs a matrix of all zeros
    pub fn zeros(rows: uint, cols : uint)-> Mat<T> {
        let m : Mat<T> = Mat::new(rows, cols);
        // zero out the memory
        unsafe { ptr::zero_memory(m.ptr, m.capacity())};
        m
    }

    pub fn ones(rows: uint, cols : uint)-> Mat<T> {
        let m : Mat<T> = Mat::new(rows, cols);
        // fill with ones
        let ptr = m.ptr;
        let o : T = One::one();
        unsafe {
            for c in range(0, cols){
                for r in range (0, rows){
                    let offset = m.cell_to_offset(r, c);
                    let p  = ptr.offset(offset as int);
                    *p = o;
                }
            }
        }
        m
    }

    pub fn from_slice(rows: uint, cols : uint, values: &[T]) -> Mat<T>{
        let mut mat : Mat<T> = Mat::new(rows, cols);
        let n_cells = mat.num_cells();
        let stride = mat.stride();
        // get a mutable slice from m
        {
            let dst_slice = mat.as_mut_slice();
            let n_values = values.len();
            // The number of entries we can copy
            let n_fill = cmp::min(n_values, n_cells);
            let mut n = 0;
            let mut offset_src = 0;
            let mut offset_dst = 0;
            for _ in range(0, cols){
                for r in range(0, rows){
                    n+=1;
                    dst_slice[offset_dst + r] = values[offset_src + r];
                    if n == n_fill {
                        break;
                    }
                }
                if n == n_fill {
                    break;
                }
                offset_src += rows;
                offset_dst += stride;
            }
        }
        // return
        mat
    }

    pub fn from_iter< A : Iterator<T>>(rows: uint, cols : uint, mut iter: A) -> Mat<T>{
        let mut mat : Mat<T> = Mat::new(rows, cols);
        let stride = mat.stride();
        // get a mutable slice from m
        {
            let dst_slice = mat.as_mut_slice();
            let mut offset_dst = 0;
            'outer: for _ in range(0, cols){
                for r in range(0, rows){
                    let next_val = iter.next();
                    match next_val{
                        Some(val) => dst_slice[offset_dst + r] = val,
                        None => break 'outer
                    };
                }
                offset_dst += stride;
            }
        }
        // return
        mat
    }
}

/// Main methods of a matrix
impl<T:Num+Ord+Copy> Mat<T> {
    pub fn num_rows(&self) -> uint {
        self.rows
    }

    pub fn num_cols(&self) -> uint {
        self.cols
    }

    pub fn size (&self)-> (uint, uint){
        (self.rows, self.cols)
    }
    pub fn num_cells(&self)->uint {
        self.rows * self.cols
    }
    /// Returns the number of actual memory elements
    /// per column stored in the memory
    pub fn stride (&self)->uint {
        self.rows
    }

    pub fn capacity(&self)-> uint {
        self.stride() * self.cols
    }

    /// Returns an unsafe pointer to the matrix's
    /// buffer.
    #[inline]
    pub fn as_ptr(&self)-> *const T{
        self.ptr as *const T
    }

    /// Returns a mutable unsafe pointer to
    /// the matrix's underlying buffer
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut T{
        self.ptr
    }

    #[inline]
    pub fn get(&self, r : uint, c : uint) -> T  {
        unsafe {
            *self.ptr.offset(self.cell_to_offset(r, c) as int)
        }
    }

    /// Converts an index to cell address (row, column)
    #[inline]
    pub fn index_to_cell(&self, index : uint) -> (uint, uint){
        let c = index / self.rows;
        let r = index - c*self.rows;
        (r, c)
    }

    /// Converts a cell address to an index (r, c) to index
    #[inline]
    pub fn cell_to_index(&self, r : uint,  c: uint) -> uint{
        c * self.rows + r
    }

    /// Converts the matrix to vector from standard library
    pub fn to_std_vec(&self) -> Vec<T> {
        let mut vec: Vec<T> = Vec::with_capacity(self.num_cells());
        // We iterate over elements in matrix and push in the vector
        let s = self.as_slice_();
        for c in range(0, self.cols){
            for r in range (0, self.rows){
                let offset = self.cell_to_offset(r, c);
                vec.push(s[offset]);
            }
        }
        vec
    }
}

impl<T:Num+Ord+Copy> Index<uint,T> for Mat<T> {
    #[inline]
    fn index<'a>(&'a self, index: &uint) -> &'a T {
        // The matrix is column major order
        let (r, c) = self.index_to_cell(*index);
        let offset = c * self.stride() + r;
        unsafe {
            &*self.ptr.offset(offset as int)
        }
    }
}

impl<T:Num+Ord+Copy> Mat<T>{
    /// This function is for internal use only.
    #[inline]
    fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        unsafe {
            mem::transmute(RawSlice {
                data: self.as_mut_ptr() as *const T,
                len: self.capacity(),
            })
        }
    }
}

impl <T:Num+Ord+Copy> Clone for Mat<T> {

    fn clone(&self )-> Mat<T> {
        let m : Mat<T> = Mat::new(self.rows, self.cols);
        unsafe{
            ptr::copy_memory(m.ptr, self.ptr as *const T, self.capacity());
        }
        m
    }
}

impl <T:Num+Ord+Copy+fmt::Show> fmt::Show for Mat<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = self.as_slice_();
        try!(write!(f, "["));
        // Here we print row by row
        for r in range (0, self.rows) {
           try!(write!(f, "\n  "));
            for c in range (0, self.cols){
                let offset = c * self.stride() + r;
                try!(write!(f, "{} ", s[offset]));
            }
        }
        try!(write!(f, "\n]\n"));
        Ok(())
    }
}

/// Matrix addition support
impl<T:Num+Ord+Copy> ops::Add<Mat<T>, Mat<T>> for Mat<T> {
    fn add(&self, rhs: &Mat<T>) -> Mat<T> {
        // Validate dimensions are same.
        if self.size() != rhs.size(){
            fail!(DimensionsMismatch.to_string());
        }
        let result : Mat<T> = Mat::new(self.rows, self.cols);
        let pa = self.ptr;
        let pb = rhs.ptr;
        let pc = result.ptr;
        let n = self.capacity();
        unsafe{
            for i_ in range(0, n){
                let i = i_ as int;
                *pc.offset(i) = *pa.offset(i) + *pb.offset(i);
            }
        }
        result
    }
}

/// Matrix subtraction support
impl<T:Num+Ord+Copy> ops::Sub<Mat<T>, Mat<T>> for Mat<T>{
    fn sub(&self, rhs: &Mat<T>) -> Mat<T> {
        // Validate dimensions are same.
        if self.size() != rhs.size(){
            fail!(DimensionsMismatch.to_string());
        }
        let result : Mat<T> = Mat::new(self.rows, self.cols);
        let pa = self.ptr;
        let pb = rhs.ptr;
        let pc = result.ptr;
        let n = self.capacity();
        unsafe{
            for i_ in range(0, n){
                let i = i_ as int;
                *pc.offset(i) = *pa.offset(i) - *pb.offset(i);
            }
        }
        result
    }
}

#[unsafe_destructor]
impl<T:Num+Ord+Copy> Drop for Mat<T> {
    fn drop(&mut self) {
        if self.num_cells() != 0 {
            unsafe {
                dealloc(self.ptr, self.capacity())
            }
        }
    }
}

/******************************************************
 *
 *   Private implementation of Mat
 *
 *******************************************************/

impl<T:Num+Ord+Copy> Mat<T> {
    /// Returns a slice into `self`.
    #[inline]
    fn as_slice_<'a>(&'a self) -> &'a [T] {
        unsafe { mem::transmute(RawSlice { data: self.as_ptr(), len: self.capacity() }) }
    }

    /// Maps a cell index to actual offset in the internal buffer
    #[inline]
    fn cell_to_offset(&self, r : uint,  c: uint)-> uint {
        c * self.stride() + r
    }
}

/***
Private helper functions follow
*/

#[inline]
unsafe fn dealloc<T>(ptr: *mut T, len: uint) {
    if mem::size_of::<T>() != 0 {
        deallocate(ptr as *mut u8,
                   len * mem::size_of::<T>(),
                   mem::min_align_of::<T>())
    }
}

/******************************************************
 *
 *   Unit tests follow.
 *
 *******************************************************/

#[cfg(test)]
mod tests {

    use  super::{Mat, MatI64};

    #[test]
    fn  create_mat0(){
        let m : MatI64 = Mat::new(3, 4);
        assert_eq!(m.num_cells(), 12);
        assert_eq!(m.size(), (3, 4));
        let v : i64 = m.get(0, 0);
        assert_eq!(v, 0i64);
    }

    #[test]
    fn test_from_iter0(){
        let m : MatI64 = Mat::from_iter(4, 4, range(1, 20));
        let b: Vec<i64> = range(1, 17).collect();
        assert!(m.as_slice_() == b.as_slice_());
        let m : MatI64 = Mat::from_iter(4, 4, range(1, 16));
        assert_eq!(m.get(0, 0), 1);
        assert_eq!(m.get(2, 2), 11);
        let mut b: Vec<i64> = range(1, 16).collect();
        b.push(0);
        assert!(m.as_slice_() == b.as_slice_());
    }

    #[test]
    fn test_index0(){
        let m : MatI64 = Mat::from_iter(4, 4, range(1, 20));
        let x = m[4];
        assert_eq!(x, 5);
    }

    #[test]
    fn test_cell_index_mapping(){
        let rows = 20;
        let cols = 10;
        let m : MatI64 = Mat::new(rows, cols);
        assert_eq!(m.index_to_cell(3 + 2*rows), (3, 2));
        assert_eq!(m.cell_to_index(3, 2), 3 + 2*rows);
        assert_eq!(m.cell_to_index(5, 7), 145);
        assert_eq!(m.index_to_cell(145), (5, 7));
    }

    #[test]
    fn test_to_std_vec(){
        let m : MatI64 = Mat::from_iter(4, 3, range(0, 12));
        let v1 = m.to_std_vec();
        let v2 : Vec<i64> = range(0, 12).collect();
        assert_eq!(v1, v2);
    }

    #[test]
    fn test_ones(){
        let m : MatI64 = Mat::ones(4, 2);
        let v = vec![1i64, 1, 1, 1, 1, 1, 1, 1];
        assert_eq!(m.to_std_vec(), v);
    }

    #[test]
    fn test_sum(){
        let m : MatI64 = Mat::ones(4, 2);
        let m2 = m  + m;
        let v = vec![2i64, 2, 2, 2, 2, 2, 2, 2];
        assert_eq!(m2.to_std_vec(), v);
    }

    #[test]
    #[should_fail]
    fn test_sum_fail(){
        let m1 : MatI64 = Mat::ones(4, 2);
        let m2 : MatI64 = Mat::ones(3, 2);
        m1 + m2;
    }

    #[test]
    fn test_sub(){
        let m : MatI64 = Mat::ones(4, 2);
        let m3 = m  + m + m;
        let m2 = m3 - m;
        let v = vec![2i64, 2, 2, 2, 2, 2, 2, 2];
        assert_eq!(m2.to_std_vec(), v);
    }

    #[test]
    #[should_fail]
    fn test_sub_fail(){
        let m1 : MatI64 = Mat::ones(4, 2);
        let m2 : MatI64 = Mat::ones(3, 2);
        m1 - m2;
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, The Radare Project. All rights reserved.
// See the COPYING file at the top-level directory of this distribution.
// Licensed under the BSD 3-Clause License:
// <http://opensource.org/licenses/BSD-3-Clause>
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::ops::{Add, BitAnd, BitOr, BitXor, Index, Mul, Not, Rem, Shl, Shr, Sub};
use std::collections::BTreeMap;
use std::rc::Rc;
use std::cell::RefCell;
use std::hash::{Hash, Hasher};
use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};

pub trait BasicOps: Add + BitAnd + BitOr + BitXor + Mul + Not + Rem
                    + Shl<Self> + Shr<Self> + Sub + Sized {}

// Some notes on design.
// Chunks are assumed to be of fixed size, that is 8 bytes (as our primary
// target is x86-64).
// Adjacent chunks are coalesced together by using the next_chunk and
// previous_chunk pointers.
// When a write starts from the middle of a chunk and number of bytes written
// exceed the size of
// the chunk, depending on the availability of the adjacent chunk, one of the
// two things will
// happen:
// 1. If the adjacent chunk already exists, this means that the write
// continues into this chunk
// 2. If the adjacent chunk does not exist then a new chunk is allocated,
// populating the
//        previous and the next_chunk pointers
// The allocator, at the time of allocation will coalesce if it finds that the
// new chunk requested
//  for is adjacent to an already exisiting chunk.
// Chunk coalescing has almost zero cost as it is effectively equivalent to
// only updating a
//  pointer value.
// Memory region maintains an ordered map of all the allocated chunks in order
// to find an
//  appropriate one when requested for.
//
// Disadvatages, using linear search on the BTreeMap might be costly. It may
// make more sense to
//  use binary search as the set is ordered.
//
//  TODO: Be able to create chunks of arbitrary size.

// Internally used associate addresses with the locations in the buffers.
#[derive(Clone, Copy, Debug)]
struct MemMetaData {
    start: u64,
    size: usize,
}

// Represents the result struct for find_memory_by_address.
// Returns the MemMetaData that the address is a part of and the offset within that chunk.
struct FindResult {
    meta: MemMetaData,
    offset: usize,
    needs_allocation: bool,
}

impl Hash for MemMetaData {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.start.hash(state)
    }
}

impl PartialOrd for MemMetaData {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.start.partial_cmp(&other.start)
    }
}

impl PartialEq for MemMetaData {
    fn eq(&self, other: &Self) -> bool {
        self.start == other.start
    }
}

impl Eq for MemMetaData { }

impl Ord for MemMetaData {
    fn cmp(&self, other: &Self) -> Ordering {
        self.start.cmp(&other.start)
    }
}

impl MemMetaData {
    pub fn new(start: u64, size: usize) -> MemMetaData {
        MemMetaData {
            start: start,
            size: size,
        }
    }
}

// Actual Chunk of that represents memory
pub struct MemoryChunk<T: BasicOps> {
    meta: MemMetaData,
    // next chunk is used to continue writes into the next chunk. This field is a `None`
    // if there is no chunk that continues the present chunk.
    // This field is basically used to coalesce two adjacent chunks together.
    next_chunk: Option<Rc<RefCell<Vec<T>>>>,
    prev_chunk: Option<Rc<RefCell<Vec<T>>>>,
    buffer: Rc<RefCell<Vec<T>>>,
    // For later use. To mark that a memory has been written out to disk and can be reused.
    in_use: bool,
}

impl<T: BasicOps> MemoryChunk<T> {
    fn new(meta: MemMetaData) -> MemoryChunk<T> {
        let buffer = Rc::new(RefCell::new(Vec::new()));
        MemoryChunk {
            meta: meta,
            next_chunk: None,
            prev_chunk: None,
            buffer: buffer,
            in_use: true,
        }
    }
}

// Memory region. Container for memory chunks.
pub struct MemoryRegion<T: BasicOps> {
    min: u64,
    max: u64,
    allocated: BTreeMap<MemMetaData, Box<MemoryChunk<T>>>,
}

impl<T: BasicOps> MemoryRegion<T> {
    pub fn new() -> MemoryRegion<T> {
        MemoryRegion {
            min: 0,
            max: 0,
            allocated: BTreeMap::new(),
        }
    }

    fn find_memory_by_address(&self, meta: &MemMetaData) -> Option<FindResult> {
        if self.min > meta.start || self.max < meta.start {
            return None;
        }
        let mut keys = self.allocated.keys().collect::<Vec<&MemMetaData>>();
        while let Some(key) = keys.pop() {
            if meta.start >= key.start && meta.start < key.start + key.size as u64 {
                let offset = meta.start - key.start;
                let needs_allocation = (meta.start + meta.size as u64) >
                                       (key.start + key.size as u64);
                return Some(FindResult {
                    meta: key.clone(),
                    offset: offset as usize,
                    needs_allocation: needs_allocation,
                });
            }
            if (key.start + key.size as u64) < meta.start {
                break;
            }
        }
        return None;
    }

    // Returns true if the two memory locations are adjacent to each other
    fn is_adjacent(mem: &MemMetaData, mem_: &MemMetaData) -> bool {
        if mem.start == mem_.start + mem_.size as u64 + 1 {
            true
        } else if mem_.start == mem.start + mem.size as u64 + 1 {
            true
        } else {
            false
        }
    }

    // Tries and coalesce all chunks that are possible.
    // TODO: Match sizes. Remove next_key if coalesced with the previous chunk.
    // Coalesce memory chunk together rather than just the buffers.
    fn coalesce_chunks(&mut self) {
        let mut keys = self.allocated.iter_mut().peekable();
        if let Some((mut key, mut cur_chunk)) = keys.next() {
            loop {
                if let Some((next_key, mut next_chunk)) = keys.next() {
                    if !MemoryRegion::<T>::is_adjacent(key, next_key) {
                        key = next_key;
                        cur_chunk = next_chunk;
                        continue;
                    }
                    if cur_chunk.next_chunk.is_none() {
                        (*cur_chunk).next_chunk = Some(next_chunk.buffer.clone());
                    }
                    if next_chunk.prev_chunk.is_none() {
                        (*next_chunk).prev_chunk = Some(cur_chunk.buffer.clone());
                    }
                    key = next_key;
                    cur_chunk = next_chunk;
                    continue;
                }
                break;
            }
        }
    }

    // Three steps to make a new chunk.
    //  - Check if the chunk already exists. If not, needs_allocation
    //  - Check if the new chunk requested for is a continuation of some other chunk, i.e. the
    //    memory can be made contiguous.
    //  - Allocate and coalesce if necessary
    fn new_chunk(&mut self, meta: &MemMetaData) {
        let mut allocation_size = meta.size;
        let mut allocation_start = meta.start;
        match self.find_memory_by_address(meta) {
            Some(ref res) => {
                if !res.needs_allocation {
                    return;
                }
                allocation_size = meta.size - (res.meta.size - res.offset);
                allocation_start = res.meta.start + res.meta.size as u64;
            },
            None => {},
        }
        // Allocate the new chunk.
        let new_meta = MemMetaData::new(allocation_start, allocation_size);
        let chunk = Box::new(MemoryChunk::new(new_meta));
        self.allocated.insert(new_meta, chunk);
        self.coalesce_chunks();
    }
}

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

    }
}
<commit_msg>Temporary commit<commit_after>// Copyright (c) 2015, The Radare Project. All rights reserved.
// See the COPYING file at the top-level directory of this distribution.
// Licensed under the BSD 3-Clause License:
// <http://opensource.org/licenses/BSD-3-Clause>
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::ops::{Add, BitAnd, BitOr, BitXor, Index, Mul, Not, Rem, Shl, Shr, Sub};
use std::collections::BTreeMap;
use std::rc::Rc;
use std::cell::{Cell, RefCell};
use std::hash::{Hash, Hasher};
use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};

pub trait BasicOps: Add + BitAnd + BitOr + BitXor + Mul + Not + Rem
                    + Shl<Self> + Shr<Self> + Sub + Sized {}

pub trait MemoryOps {
    type DataType;
    fn read(&self, address: u64, size: usize) -> Self::DataType;
    fn write(&self, address: u64, size: usize, data: Self::DataType);
    // Nop by default
    fn dump_memory(&self) { }
}

// Some notes on design.
// Chunks are assumed to be of fixed size, that is 8 bytes (as our primary
// target is x86-64).
// Adjacent chunks are coalesced together by using the next_chunk and
// previous_chunk pointers.
// When a write starts from the middle of a chunk and number of bytes written
// exceed the size of
// the chunk, depending on the availability of the adjacent chunk, one of the
// two things will
// happen:
// 1. If the adjacent chunk already exists, this means that the write
// continues into this chunk
// 2. If the adjacent chunk does not exist then a new chunk is allocated,
// populating the
//        previous and the next_chunk pointers
// The allocator, at the time of allocation will coalesce if it finds that the
// new chunk requested
//  for is adjacent to an already exisiting chunk.
// Chunk coalescing has almost zero cost as it is effectively equivalent to
// only updating a
//  pointer value.
// Memory region maintains an ordered map of all the allocated chunks in order
// to find an
//  appropriate one when requested for.
//
// Disadvatages, using linear search on the BTreeMap might be costly. It may
// make more sense to
//  use binary search as the set is ordered.
//
//  TODO: Be able to create chunks of arbitrary size.

// Internally used associate addresses with the locations in the buffers.
#[derive(Clone, Debug)]
struct MemMetaData {
    start: u64,
    size: Cell<usize>,
}

impl Hash for MemMetaData {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.start.hash(state)
    }
}

impl PartialOrd for MemMetaData {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.start.partial_cmp(&other.start)
    }
}

impl PartialEq for MemMetaData {
    fn eq(&self, other: &Self) -> bool {
        self.start == other.start
    }
}

impl Eq for MemMetaData { }

impl Ord for MemMetaData {
    fn cmp(&self, other: &Self) -> Ordering {
        self.start.cmp(&other.start)
    }
}

impl MemMetaData {
    pub fn new(start: u64, size: usize) -> MemMetaData {
        MemMetaData {
            start: start,
            size: Cell::new(size),
        }
    }

    pub fn size(&self) -> usize {
        self.size.get()
    }

    pub fn sizeu64(&self) -> u64 {
        self.size.get() as u64
    }

    pub fn extend_by(&self, n: usize) {
        self.size.set(self.size() + n);
    }
}

// Represents the result struct for find_memory_by_address.
// Returns the MemMetaData that the address is a part of and the offset within that chunk.
struct FindResult {
    meta: MemMetaData,
    offset: usize,
    needs_allocation: bool,
}

// Actual Chunk of that represents memory
pub struct _MemoryChunk<T: BasicOps> {
    // next chunk is used to continue writes into the next chunk. This field is a `None`
    // if there is no chunk that continues the present chunk.
    // This field is basically used to coalesce two adjacent chunks together.
    next_chunk: Option<MemoryChunk<T>>,
    buffer: Rc<RefCell<Vec<T>>>,
    // For later use. To mark that a memory has been written out to disk and can be reused.
    in_use: bool,
}

type MemoryChunk<T> = Rc<RefCell<_MemoryChunk<T>>>;

impl<T: BasicOps> _MemoryChunk<T> {
    fn new() -> _MemoryChunk<T> {
        let buffer = Rc::new(RefCell::new(Vec::new()));
        _MemoryChunk {
            next_chunk: None,
            buffer: buffer,
            in_use: true,
        }
    }
}

// Memory region. Container for memory chunks.
pub struct MemoryRegion<T: BasicOps> {
    min: u64,
    max: u64,
    allocated: BTreeMap<MemMetaData, MemoryChunk<T>>,
}

impl<T: BasicOps> MemoryRegion<T> {
    pub fn new() -> MemoryRegion<T> {
        MemoryRegion {
            min: 0,
            max: 0,
            allocated: BTreeMap::new(),
        }
    }

    fn find_memory_by_address(&self, meta: &MemMetaData) -> Option<FindResult> {
        if self.min > meta.start || self.max < meta.start {
            return None;
        }
        let mut keys = self.allocated.keys().collect::<Vec<&MemMetaData>>();
        while let Some(key) = keys.pop() {
            if meta.start >= key.start && meta.start < key.start + key.sizeu64() {
                let offset = meta.start - key.start;
                let needs_allocation = (meta.start + meta.sizeu64()) >
                                       (key.start + key.sizeu64());
                return Some(FindResult {
                    meta: key.clone(),
                    offset: offset as usize,
                    needs_allocation: needs_allocation,
                });
            }
            if key.start + key.sizeu64() < meta.start {
                break;
            }
        }
        return None;
    }

    // Returns true if the two memory locations are adjacent to each other
    fn is_adjacent(mem: &MemMetaData, mem_: &MemMetaData) -> bool {
        if mem.start == mem_.start + mem_.sizeu64() + 1 {
            true
        } else if mem_.start == mem.start + mem.sizeu64() + 1 {
            true
        } else {
            false
        }
    }

    // Tries and coalesce all chunks that are possible.
    fn coalesce_chunks(&mut self) {
        let mut compacted = Vec::<MemMetaData>::new();
        {
            let mut keys = self.allocated.iter_mut().peekable();
            if let Some((mut key, mut cur_chunk)) = keys.next() {
                loop {
                    if let Some((next_key, mut next_chunk)) = keys.next() {
                        if !MemoryRegion::<T>::is_adjacent(key, next_key) {
                            key = next_key;
                            cur_chunk = next_chunk;
                            continue;
                        }

                        assert!(cur_chunk.borrow().next_chunk.is_none());
                        (*cur_chunk).borrow_mut().next_chunk = Some(next_chunk.clone());
                        key.extend_by(next_key.size());

                        key = next_key;
                        cur_chunk = next_chunk;

                        compacted.push(next_key.clone());
                        continue;
                    }
                    break;
                }
            }
        }
        for key in &compacted {
            self.allocated.remove(key);
        }
    }

    fn new_chunk(&mut self, meta: &MemMetaData) {
        let (allocation_size, allocation_start) = match self.find_memory_by_address(meta) {
            Some(ref res) => {
                match res.needs_allocation {
                    true => (meta.size() - res.meta.size() + res.offset,
                              res.meta.start + res.meta.sizeu64()),
                    false => (0, 0),
                }
            },
            None => (meta.size(), meta.start),
        };
        if allocation_size > 0 {
            let new_meta = MemMetaData::new(allocation_start, allocation_size);
            let chunk = Rc::new(RefCell::new(_MemoryChunk::new()));
            self.allocated.insert(new_meta, chunk);
            self.coalesce_chunks();
        }
    }

    pub fn read(&self, address: u64, size: usize) -> Option<&[T]> {
        unimplemented!()
    }

    pub fn write(&mut self, address: u64, size: usize, data: &[T]) {
        unimplemented!()
    }

    pub fn dump_memory(&self) {
        unimplemented!()
    }
}

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

    }
}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub, Div};
use std::collections::HashMap;
use std::iter::FromIterator;
use std::iter::repeat;
use std::fmt::{Debug, Formatter, Error};
use std::cmp::Ordering::Equal;
use std::ops::Drop;
use std::cmp;

#[derive(Clone,)]
pub struct WordVec {
    pub word: String,
    pub count: u64,
    vec: Vec<f32>,
}

impl PartialEq for WordVec {
    fn eq(&self, other: &WordVec) -> bool {
        self.vec == other.vec
    }
}

impl Debug for WordVec {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        try!(self.word.fmt(fmt));
        try!(fmt.write_str(": "));
        try!(self.count.fmt(fmt));
        try!(fmt.write_str(", "));
        self.vec.iter().take(5).collect::<Vec<_>>().fmt(fmt)
    }
}

impl WordVec {

    fn dot_prod(&self, other: &WordVec) -> f32 {
        self.vec.iter()
                .zip(other.vec.iter())
                .map(|(x, y)| x * y)
                .fold(0.0, |x, y| x + y)
    }

    fn magnitude(&self) -> f32 {
        self.vec.iter()
                .map(|x| x * x)
                .fold(0.0, |x, y| x + y)
                .sqrt()
    }

    pub fn distance(&self, other: &WordVec) -> f32 {
        self.vec.iter().zip(other.vec.iter())
                .map(|(x, y)| (x - y)*(x - y))
                .fold(0.0, |x, y| x + y)
                .sqrt()
    }

    fn new(word: String, num_words: usize) -> WordVec {
        WordVec {
            word: word,
            count: 0,
            vec: repeat(0.0).take(num_words).collect(),
        }
    }

    fn normalize(&mut self) {
        let count = self.count as f32;
        for f in &mut self.vec {
            *f /= count;
        }
    }

    fn inc(&mut self, i: usize) {
        self.vec[i] += 1.0;
    }

}

impl Div<i32> for WordVec {
    type Output = WordVec;

    fn div(mut self, i: i32) -> WordVec {
        for f in &mut self.vec {
            *f /= i as f32;
        }

        self
    }
}

impl<'a> Add<&'a WordVec> for WordVec {
    type Output = WordVec;

    fn add(self, other: &WordVec) -> WordVec {
        debug_assert!(self.vec.len() == other.vec.len());
        let mut newvec = WordVec {
            word: format!("{} + {}", &self.word, &other.word),
            count: 0,
            vec: self.vec,
        };

        for i in 0..newvec.vec.len() {
            newvec.vec[i] += other.vec[i];
        }

        newvec
    }
}

impl<'a> Sub<&'a WordVec> for WordVec {
    type Output = WordVec;

    fn sub(self, other: &WordVec) -> WordVec {
        debug_assert!(self.vec.len() == other.vec.len());
        let mut newvec = WordVec {
            word: format!("{} - {}", &self.word, &other.word),
            count: 0,
            vec: self.vec,
        };

        for i in 0..(newvec.vec.len()) {
            newvec.vec[i] -= other.vec[i];
        }

        newvec
    }
}

pub struct LanguageModel {
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVec>,
}

pub struct LanguageModelBuilder {
    window_radius: usize,
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVec>,
    sentence: Vec<Option<usize>>,
}

pub struct WordAcceptor<'a> {
    builder: &'a mut LanguageModelBuilder,
}

impl LanguageModelBuilder {
    pub fn new(window_radius: usize, words: Vec<String>) -> LanguageModelBuilder {

        let word_vecs = words.iter()
                             .map(|s| WordVec::new(s.clone(), words.len()))
                             .collect();

        let words = HashMap::from_iter(
                        words.into_iter()
                             .enumerate()
                             .map(|(a, b)| (b, a)));

        LanguageModelBuilder {
            window_radius: window_radius,
            words: words,
            word_vecs: word_vecs,
            sentence: vec![],
        }
    }

    pub fn build(mut self) -> LanguageModel {
        for vec in self.word_vecs.iter_mut() {
            vec.normalize();
        }

        LanguageModel {
            words: self.words,
            word_vecs: self.word_vecs,
        }
    }

    pub fn new_sentence<'a>(&'a mut self) -> WordAcceptor<'a> {
        WordAcceptor {
            builder: self,
        }
    }

    fn word_seen(&mut self, word: usize) {
        self.word_vecs[word].count += 1;
    }
}

impl<'a> WordAcceptor<'a> {
    pub fn add_word(&mut self, word: &str) {
        let idx_opt = self.builder.words.get(word).map(|w| *w);

        if let Some(next_idx) = idx_opt {
            self.builder.word_seen(next_idx);
            self.builder.sentence.push(Some(next_idx));
        }
        else {
            self.builder.sentence.push(None);
        }
    }
}

impl<'a> Drop for WordAcceptor<'a> {
    fn drop(&mut self) {
        let LanguageModelBuilder {
            ref mut sentence,
            ref mut word_vecs,
            window_radius,
            ..
        } = *self.builder;

        for (i, &word_idx) in sentence.iter().enumerate() {
            let start = cmp::max(0, i as isize - window_radius as isize) as usize;
            let end = cmp::min(sentence.len(), i + window_radius + 1);
            for &j in &sentence[start..end] {
                match (word_idx, j) {
                    (Some(w), Some(j)) if w != j =>
                        word_vecs[w].inc(j),
                    _ => {},
                }
            }
        }

        sentence.clear();
    }
}

impl LanguageModel {
    pub fn get(&self, word: &str) -> Option<&WordVec> {
        self.words.get(word).map(|i| &self.word_vecs[*i])
    }

    pub fn nearest_words(&self, word: &WordVec) -> Vec<&WordVec> {
        let mut vec_refs = self.word_vecs.iter().filter_map(|w| {
            let dist = w.distance(word);
            if w.word != word.word {
                Some((dist, w))
            } else {
                None
            }
        }).collect::<Vec<_>>();
        vec_refs.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or_else(|| {
            println!("bad vector: {:?}, {:?}", a, b);
            Equal
        }));
        vec_refs.into_iter().map(|x| x.1).collect()
    }
}

#[cfg(test)]
mod test {
    use super::{WordVec, LanguageModel, LanguageModelBuilder};

    #[test]
    fn test_accept_sentences() {
        let words = "foo bar baz blort".words().map(|w| w.to_string()).collect::<Vec<_>>();
        let mut builder = LanguageModelBuilder::new(1, words);

        let input = "x foo bar baz x x x x x x x blort".words();

        {
            let mut acc = builder.new_sentence();
            for word in input {
                acc.add_word(word);
            }
        }

        let model = builder.build();
        let foo = model.get("foo").unwrap();
        let baz = model.get("baz").unwrap();
        let bar = model.get("bar").unwrap();
        let blort = model.get("blort").unwrap();

        assert!(foo.distance(baz) < foo.distance(blort));
        assert!(foo.distance(bar) == bar.distance(baz));

    }
}
<commit_msg>implement serialization of language model<commit_after>use std::ops::{Add, Sub, Div};
use std::collections::HashMap;
use std::iter::FromIterator;
use std::iter::repeat;
use std::fmt::{Debug, Formatter, Error};
use std::cmp::Ordering::Equal;
use std::ops::Drop;
use std::cmp;
use std::path::Path;
use std::io::{BufWriter, Write, BufReader, Read, BufRead};
use std::fs::File;
use std::mem;

#[derive(Clone)]
pub struct WordVec {
    pub word: String,
    pub count: u64,
    vec: Vec<f32>,
}

impl PartialEq for WordVec {
    fn eq(&self, other: &WordVec) -> bool {
        self.vec == other.vec
    }
}

impl Debug for WordVec {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        try!(self.word.fmt(fmt));
        try!(fmt.write_str(": "));
        try!(self.count.fmt(fmt));
        try!(fmt.write_str(", "));
        self.vec.iter().take(5).collect::<Vec<_>>().fmt(fmt)
    }
}

impl WordVec {

    fn dot_prod(&self, other: &WordVec) -> f32 {
        self.vec.iter()
                .zip(other.vec.iter())
                .map(|(x, y)| x * y)
                .fold(0.0, |x, y| x + y)
    }

    fn magnitude(&self) -> f32 {
        self.vec.iter()
                .map(|x| x * x)
                .fold(0.0, |x, y| x + y)
                .sqrt()
    }

    pub fn distance(&self, other: &WordVec) -> f32 {
        self.vec.iter().zip(other.vec.iter())
                .map(|(x, y)| (x - y)*(x - y))
                .fold(0.0, |x, y| x + y)
                .sqrt()
    }

    fn new(word: String, num_words: usize) -> WordVec {
        WordVec {
            word: word,
            count: 0,
            vec: repeat(0.0).take(num_words).collect(),
        }
    }

    fn normalize(&mut self) {
        let count = self.count as f32;
        for f in &mut self.vec {
            *f /= count;
        }
    }

    fn inc(&mut self, i: usize) {
        self.vec[i] += 1.0;
    }

}

impl Div<i32> for WordVec {
    type Output = WordVec;

    fn div(mut self, i: i32) -> WordVec {
        for f in &mut self.vec {
            *f /= i as f32;
        }

        self
    }
}

impl<'a> Add<&'a WordVec> for WordVec {
    type Output = WordVec;

    fn add(self, other: &WordVec) -> WordVec {
        debug_assert!(self.vec.len() == other.vec.len());
        let mut newvec = WordVec {
            word: format!("{} + {}", &self.word, &other.word),
            count: 0,
            vec: self.vec,
        };

        for i in 0..newvec.vec.len() {
            newvec.vec[i] += other.vec[i];
        }

        newvec
    }
}

impl<'a> Sub<&'a WordVec> for WordVec {
    type Output = WordVec;

    fn sub(self, other: &WordVec) -> WordVec {
        debug_assert!(self.vec.len() == other.vec.len());
        let mut newvec = WordVec {
            word: format!("{} - {}", &self.word, &other.word),
            count: 0,
            vec: self.vec,
        };

        for i in 0..(newvec.vec.len()) {
            newvec.vec[i] -= other.vec[i];
        }

        newvec
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct LanguageModel {
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVec>,
}

pub struct LanguageModelBuilder {
    window_radius: usize,
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVec>,
    sentence: Vec<Option<usize>>,
}

pub struct WordAcceptor<'a> {
    builder: &'a mut LanguageModelBuilder,
}

impl LanguageModelBuilder {
    pub fn new(window_radius: usize, words: Vec<String>) -> LanguageModelBuilder {

        let word_vecs = words.iter()
                             .map(|s| WordVec::new(s.clone(), words.len()))
                             .collect();

        let words = HashMap::from_iter(
                        words.into_iter()
                             .enumerate()
                             .map(|(a, b)| (b, a)));

        LanguageModelBuilder {
            window_radius: window_radius,
            words: words,
            word_vecs: word_vecs,
            sentence: vec![],
        }
    }

    pub fn build(mut self) -> LanguageModel {
        for vec in self.word_vecs.iter_mut() {
            vec.normalize();
        }

        LanguageModel {
            words: self.words,
            word_vecs: self.word_vecs,
        }
    }

    pub fn new_sentence<'a>(&'a mut self) -> WordAcceptor<'a> {
        WordAcceptor {
            builder: self,
        }
    }

    fn word_seen(&mut self, word: usize) {
        self.word_vecs[word].count += 1;
    }
}

impl<'a> WordAcceptor<'a> {
    pub fn add_word(&mut self, word: &str) {
        let idx_opt = self.builder.words.get(word).map(|w| *w);

        if let Some(next_idx) = idx_opt {
            self.builder.word_seen(next_idx);
            self.builder.sentence.push(Some(next_idx));
        }
        else {
            self.builder.sentence.push(None);
        }
    }
}

impl<'a> Drop for WordAcceptor<'a> {
    fn drop(&mut self) {
        let LanguageModelBuilder {
            ref mut sentence,
            ref mut word_vecs,
            window_radius,
            ..
        } = *self.builder;

        for (i, &word_idx) in sentence.iter().enumerate() {
            let start = cmp::max(0, i as isize - window_radius as isize) as usize;
            let end = cmp::min(sentence.len(), i + window_radius + 1);
            for &j in &sentence[start..end] {
                match (word_idx, j) {
                    (Some(w), Some(j)) if w != j =>
                        word_vecs[w].inc(j),
                    _ => {},
                }
            }
        }

        sentence.clear();
    }
}

impl LanguageModel {
    pub fn get(&self, word: &str) -> Option<&WordVec> {
        self.words.get(word).map(|i| &self.word_vecs[*i])
    }

    pub fn nearest_words(&self, word: &WordVec) -> Vec<&WordVec> {
        let mut vec_refs = self.word_vecs.iter().filter_map(|w| {
            let dist = w.distance(word);
            if w.word != word.word {
                Some((dist, w))
            } else {
                None
            }
        }).collect::<Vec<_>>();
        vec_refs.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or_else(|| {
            println!("bad vector: {:?}, {:?}", a, b);
            Equal
        }));
        vec_refs.into_iter().map(|x| x.1).collect()
    }

    pub fn save(&self, path: &Path) {
        let mut file = BufWriter::new(File::create(path).unwrap());

        write_raw(self.word_vecs.len(), &mut file);
        file.write(&[b'\n']);

        for vec in &self.word_vecs {
            file.write(vec.word.as_bytes());
            file.write(&[b':']);
            let count = vec.count;
            write_raw(count, &mut file);
            for f in &vec.vec {
                write_raw(*f, &mut file)
            }
            file.write(&[b'\n']);
        }

    }

    pub fn load(path: &Path) -> LanguageModel {
        let mut file = BufReader::new(File::open(path).unwrap());
        let mut word_vecs = Vec::new();

        let size: u64 = read_raw(&mut file);
        read_byte(b'\n', &mut file);

        for i in 0..size {
            let mut word: Vec<u8> = Vec::new();
            file.read_until(b':', &mut word);
            assert_eq!(Some(b':'), word.pop());
            let word = String::from_utf8(word).unwrap();

            let count: u64 = read_raw(&mut file);

            let mut vec: Vec<f32> = repeat(0f32).take(size as usize).collect();
            for f in &mut vec {
                *f = read_raw(&mut file);
            }

            read_byte(b'\n', &mut file);

            word_vecs.push(WordVec {
                word: word,
                count: count,
                vec: vec,
            });
        }

        let words: HashMap<_, _> = word_vecs.iter()
                                            .map(|v| v.word.clone())
                                            .enumerate()
                                            .map(|(i, w)| (w, i))
                                            .collect();

        LanguageModel {
            words: words,
            word_vecs: word_vecs,
        }
    }
}

fn read_byte<R: Read>(b: u8, read: &mut R) {
    let buf = &mut [0];
    read.read(buf);
    assert_eq!(&[b'\n'], buf);
}

fn read_raw<T: Copy, R: Read>(reader: &mut BufReader<R>) -> T {
    let mut buffer = [0u8; 64];
    let t_size = mem::size_of::<T>();
    assert!(t_size <= buffer.len());

    let size = reader.read(&mut buffer[0..t_size]).unwrap();
    assert_eq!(t_size, size);

    unsafe {
        let bptr: *mut T = mem::transmute((&buffer).as_ptr());
        *bptr
    }
}

fn write_raw<T: Copy, F: Write>(t: T, writer: &mut BufWriter<F>) {
    let mut buffer = [0u8; 64];
    let t_size = mem::size_of::<T>();
    assert!(t_size <= buffer.len());
    unsafe {
        let bptr: *mut T = mem::transmute((&buffer).as_ptr());
        *bptr = t;
    }

    writer.write(&buffer[0..t_size]);
}

#[cfg(test)]
mod test {
    use super::{WordVec, LanguageModel, LanguageModelBuilder};
    use std::path::Path;

    fn get_model() -> LanguageModel {
        let words = "foo bar baz blort".words().map(|w| w.to_string()).collect::<Vec<_>>();
        let mut builder = LanguageModelBuilder::new(1, words);

        let input = "x foo bar baz x x x x x x x blort".words();

        {
            let mut acc = builder.new_sentence();
            for word in input {
                acc.add_word(word);
            }
        }

        builder.build()
    }

    #[test]
    fn test_accept_sentences() {
        let model = get_model();
        let foo = model.get("foo").unwrap();
        let baz = model.get("baz").unwrap();
        let bar = model.get("bar").unwrap();
        let blort = model.get("blort").unwrap();

        assert!(foo.distance(baz) < foo.distance(blort));
        assert!(foo.distance(bar) == bar.distance(baz));
    }

    #[test]
    fn test_serialization() {
        let model = get_model();
        let path = Path::new("/tmp/model.data");
        model.save(&path);

        let loaded_model = LanguageModel::load(path);
        assert_eq!(model, loaded_model);
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use na::{Vector2, Vector3};
use std::collections::HashSet;
use std::collections::HashMap;
use std::hash::Hash;
use std::collections::BinaryHeap;
use std::cmp::Ordering;

use self::rand::{Rng,StdRng};

use terrain;
use prim;

const STEP: i64 = prim::TILE_SIZE as i64;

pub type Path = Vec<Vector2<i64>>;

pub fn find_flag_positions(ground: &terrain::Ground, rand: &mut StdRng) -> Vec<prim::Flag> {
    let mut flag_positions = Vec::new();
    loop {
        let xp = (rand.gen::<f64>() * 0.8 + 0.1) * prim::DIM - prim::HDIM;
        let zp = (rand.gen::<f64>() * 0.8 + 0.1) * prim::DIM - prim::HDIM;
        let yp = terrain::get_height_at(&ground, xp, zp);
        if yp > 10.0 {
            flag_positions.push(Vector3::new(xp, yp, zp));
        }
        if flag_positions.len() == 10 {
            break;
        }
    }

    flag_positions.into_iter().map(|p| prim::Flag {
        position: p,
        flag_state: prim::FlagState::Free,
        flag_timer: prim::FLAG_TIMER,
    }).collect()
}

pub fn find_base_positions(ground: &terrain::Ground, rand: &mut StdRng) -> [Vector3<f64>; 2] {
    loop {
        let x1 = -prim::HDIM + prim::TILE_SIZE * 2.0;
        let x2 =  prim::HDIM - prim::TILE_SIZE * 2.0;
        let z1 = (rand.gen::<f64>() * 0.8 + 0.1) * prim::DIM - prim::HDIM;
        let z2 = (rand.gen::<f64>() * 0.8 + 0.1) * prim::DIM - prim::HDIM;
        let y1 = terrain::get_height_at(&ground, x1, z1);
        let y2 = terrain::get_height_at(&ground, x2, z2);
        if y1 < 10.0 || y2 < 10.0 {
            continue;
        }

        let bp = [
                    Vector3::new(x1, y1, z1),
                    Vector3::new(x2, y2, z2),
        ];
        let path = find_path(&ground, bp[0], bp[1], "base_position", 1000);

        match path {
            None    => (),
            Some(_) => return bp,
        }
    }
}

pub fn vec_to_grid(v: Vector3<f64>) -> Vector2<i64> {
    fn round(n: f64) -> i64 {
        (prim::TILE_SIZE * (n / prim::TILE_SIZE).round()) as i64
    };

    Vector2::new(round(v.x), round(v.z))
}

pub fn find_path(ground: &terrain::Ground, p1: Vector3<f64>, p2: Vector3<f64>, user: &str, limit: usize) -> Option<Path> {
    let pn1 = vec_to_grid(p1);
    let pn2 = vec_to_grid(p2);

    let graph = |n: &Vector2<i64>| {
        let mut ret = Vec::new();
        let mut j = -STEP;
        while j <= STEP {
            let mut i = -STEP;
            while i <= STEP {
                if i == 0 && j == 0 {
                    i += STEP;
                    continue;
                }

                let pos = Vector2::new(n.x + i as i64, n.y + j as i64);
                i += STEP;
                if terrain::get_height_at(ground, pos.x as f64, pos.y as f64) < 1.0 {
                    continue;
                }
                if pos.x <= -prim::HDIM as i64 || pos.x >= prim::HDIM as i64 ||
                   pos.y <= -prim::HDIM as i64 || pos.y >= prim::HDIM as i64 {
                       continue;
                }

                ret.push(pos);
            }
            j += STEP;
        }
        ret
    };

    let distance = |n1: &Vector2<i64>, n2: &Vector2<i64>| {
        let dx = n2.x - n1.x;
        let dy = n2.y - n1.y;
        ((dx * dx + dy * dy) as f64).sqrt() as u64
    };

    let heuristic = |n1: &Vector2<i64>| {
        let dx = pn2.x - n1.x;
        let dy = pn2.y - n1.y;
        (dx.abs() + dy.abs()) as u64
    };

    let goal = |n1: &Vector2<i64>| {
        let dx = pn2.x - n1.x;
        let dy = pn2.y - n1.y;
        dx.abs() < STEP / 2 && dy.abs() < STEP / 2
    };

    let mut mp = astar(graph, distance, heuristic, goal, pn1, limit);
    match mp {
        None            => (),
        Some(ref mut p) => {
            p.push(Vector2::new(p2.x as i64, p2.z as i64));
        }
    }

    match mp {
        None        => println!("[{}] No path found", user),
        Some(ref p) => {
            println!("[{}] Path found with {} nodes", user, p.len());
        }
    }
    mp
}

fn astar<G, D, H, Goal, A>(graph: G, distance: D, heuristic: H, goal: Goal, start: A, limit: usize) -> Option<Vec<A>>
    where G: Fn(&A) -> Vec<A>,
          D: Fn(&A, &A) -> u64,
          Goal: Fn(&A) -> bool,
          H: Fn(&A) -> u64,
          A: Eq + Hash + Copy {
    struct State<B> {
        cost: u64,
        node: B
    }

    impl<B> Eq for State<B> {}
    impl<B> PartialEq for State<B> {
        fn eq(&self, other: &State<B>) -> bool {
            other.cost == self.cost
        }
    }

    impl<B> Ord for State<B> {
        fn cmp(&self, other: &State<B>) -> Ordering {
            other.cost.cmp(&self.cost)
        }
    }

    impl<B> PartialOrd for State<B> {
        fn partial_cmp(&self, other: &State<B>) -> Option<Ordering> {
            Some(self.cmp(&other))
        }
    }

    let mut visited = HashSet::new();
    let mut open = BinaryHeap::new();
    let mut cost_here = HashMap::new();
    let mut parents = HashMap::new();
    let mut ret: Vec<A> = Vec::new();
    let mut curr_backtrack_node = None;

    open.push(State{cost:0, node: start});
    while !open.is_empty() {
        let current = open.pop().unwrap().node;
        if visited.len() > limit {
            break;
        }

        if visited.contains(&current) {
            continue;
        }

        if goal(&current) {
            curr_backtrack_node = Some(current);
            break;
        }
        visited.insert(current);

        let children = graph(&current);
        for child in children.into_iter() {
            if visited.contains(&child) {
                continue;
            }

            let edge_cost = distance(&current, &child);
            let this_g_cost = cost_here.get(&current).unwrap_or(&0) + edge_cost;
            let mut add_this_as_parent = true;
            {
                let already_open_child = cost_here.get(&child);
                match already_open_child {
                    Some(&cost_prev) => if cost_prev <= this_g_cost { add_this_as_parent = false; },
                    None             => (),
                }
            }
            if add_this_as_parent {
                let this_f_cost = this_g_cost + heuristic(&child);
                parents.insert(child, current);
                open.push(State{cost: this_f_cost, node: child});
                cost_here.insert(child, this_g_cost);
            }
        }
    }

    if curr_backtrack_node.is_none() {
        return None;
    }

    loop {
        match curr_backtrack_node {
            None    => break,
            Some(n) => {
                ret.push(n);
                let parent = parents.get(&n);
                match parent {
                    None     => break,
                    Some(n2) => curr_backtrack_node = Some(*n2),
                }
            }
        }
    }
    ret.reverse();
    Some(ret)
}
<commit_msg>make base location finding more robust<commit_after>extern crate rand;

use na::{Vector2, Vector3};
use std::collections::HashSet;
use std::collections::HashMap;
use std::hash::Hash;
use std::collections::BinaryHeap;
use std::cmp::Ordering;

use self::rand::{Rng,StdRng};

use terrain;
use prim;

const STEP: i64 = prim::TILE_SIZE as i64;

pub type Path = Vec<Vector2<i64>>;

pub fn find_flag_positions(ground: &terrain::Ground, rand: &mut StdRng) -> Vec<prim::Flag> {
    let mut flag_positions = Vec::new();
    loop {
        let xp = (rand.gen::<f64>() * 0.8 + 0.1) * prim::DIM - prim::HDIM;
        let zp = (rand.gen::<f64>() * 0.8 + 0.1) * prim::DIM - prim::HDIM;
        let yp = terrain::get_height_at(&ground, xp, zp);
        if yp > 10.0 {
            flag_positions.push(Vector3::new(xp, yp, zp));
        }
        if flag_positions.len() == 10 {
            break;
        }
    }

    flag_positions.into_iter().map(|p| prim::Flag {
        position: p,
        flag_state: prim::FlagState::Free,
        flag_timer: prim::FLAG_TIMER,
    }).collect()
}

pub fn find_base_positions(ground: &terrain::Ground, rand: &mut StdRng) -> [Vector3<f64>; 2] {
    for i in 0..200 {
        let (x1, x2) = if i < 100 {
            let x1 = -prim::HDIM + prim::TILE_SIZE * 2.0;
            let x2 =  prim::HDIM - prim::TILE_SIZE * 2.0;
            (x1, x2)
        } else {
            let x1 =   (rand.gen::<f64>() * 0.3) * prim::DIM - prim::HDIM + prim::TILE_SIZE * 2.0;
            let x2 = -((rand.gen::<f64>() * 0.3) * prim::DIM - prim::HDIM + prim::TILE_SIZE * 2.0);
            (x1, x2)
        };
        let z1 = (rand.gen::<f64>() * 0.8 + 0.1) * prim::DIM - prim::HDIM;
        let z2 = (rand.gen::<f64>() * 0.8 + 0.1) * prim::DIM - prim::HDIM;
        let y1 = terrain::get_height_at(&ground, x1, z1);
        let y2 = terrain::get_height_at(&ground, x2, z2);
        if y1 < 10.0 || y2 < 10.0 {
            continue;
        }
        if (x2 - x1) + (z2 - z1).abs() < prim::DIM * 0.5 {
            continue;
        }

        let bp = [
                    Vector3::new(x1, y1, z1),
                    Vector3::new(x2, y2, z2),
        ];
        let path = find_path(&ground, bp[0], bp[1], "base_position", 20000);

        match path {
            None    => (),
            Some(_) => return bp,
        }
    }
    panic!("Unable to find base positions!")
}

pub fn vec_to_grid(v: Vector3<f64>) -> Vector2<i64> {
    fn round(n: f64) -> i64 {
        (prim::TILE_SIZE * (n / prim::TILE_SIZE).round()) as i64
    };

    Vector2::new(round(v.x), round(v.z))
}

pub fn find_path(ground: &terrain::Ground, p1: Vector3<f64>, p2: Vector3<f64>, user: &str, limit: usize) -> Option<Path> {
    let pn1 = vec_to_grid(p1);
    let pn2 = vec_to_grid(p2);

    let graph = |n: &Vector2<i64>| {
        let mut ret = Vec::new();
        let mut j = -STEP;
        while j <= STEP {
            let mut i = -STEP;
            while i <= STEP {
                if i == 0 && j == 0 {
                    i += STEP;
                    continue;
                }

                let pos = Vector2::new(n.x + i as i64, n.y + j as i64);
                i += STEP;
                if terrain::get_height_at(ground, pos.x as f64, pos.y as f64) < 1.0 {
                    continue;
                }
                if pos.x <= -prim::HDIM as i64 || pos.x >= prim::HDIM as i64 ||
                   pos.y <= -prim::HDIM as i64 || pos.y >= prim::HDIM as i64 {
                       continue;
                }

                ret.push(pos);
            }
            j += STEP;
        }
        ret
    };

    let distance = |n1: &Vector2<i64>, n2: &Vector2<i64>| {
        let dx = n2.x - n1.x;
        let dy = n2.y - n1.y;
        ((dx * dx + dy * dy) as f64).sqrt() as u64
    };

    let heuristic = |n1: &Vector2<i64>| {
        let dx = pn2.x - n1.x;
        let dy = pn2.y - n1.y;
        (dx.abs() + dy.abs()) as u64
    };

    let goal = |n1: &Vector2<i64>| {
        let dx = pn2.x - n1.x;
        let dy = pn2.y - n1.y;
        dx.abs() < STEP / 2 && dy.abs() < STEP / 2
    };

    let mut mp = astar(graph, distance, heuristic, goal, pn1, limit);
    match mp {
        None            => (),
        Some(ref mut p) => {
            p.push(Vector2::new(p2.x as i64, p2.z as i64));
        }
    }

    match mp {
        None        => println!("[{}] No path found", user),
        Some(ref p) => {
            println!("[{}] Path found with {} nodes", user, p.len());
        }
    }
    mp
}

fn astar<G, D, H, Goal, A>(graph: G, distance: D, heuristic: H, goal: Goal, start: A, limit: usize) -> Option<Vec<A>>
    where G: Fn(&A) -> Vec<A>,
          D: Fn(&A, &A) -> u64,
          Goal: Fn(&A) -> bool,
          H: Fn(&A) -> u64,
          A: Eq + Hash + Copy {
    struct State<B> {
        cost: u64,
        node: B
    }

    impl<B> Eq for State<B> {}
    impl<B> PartialEq for State<B> {
        fn eq(&self, other: &State<B>) -> bool {
            other.cost == self.cost
        }
    }

    impl<B> Ord for State<B> {
        fn cmp(&self, other: &State<B>) -> Ordering {
            other.cost.cmp(&self.cost)
        }
    }

    impl<B> PartialOrd for State<B> {
        fn partial_cmp(&self, other: &State<B>) -> Option<Ordering> {
            Some(self.cmp(&other))
        }
    }

    let mut visited = HashSet::new();
    let mut open = BinaryHeap::new();
    let mut cost_here = HashMap::new();
    let mut parents = HashMap::new();
    let mut ret: Vec<A> = Vec::new();
    let mut curr_backtrack_node = None;

    open.push(State{cost:0, node: start});
    while !open.is_empty() {
        let current = open.pop().unwrap().node;
        if visited.len() > limit {
            break;
        }

        if visited.contains(&current) {
            continue;
        }

        if goal(&current) {
            curr_backtrack_node = Some(current);
            break;
        }
        visited.insert(current);

        let children = graph(&current);
        for child in children.into_iter() {
            if visited.contains(&child) {
                continue;
            }

            let edge_cost = distance(&current, &child);
            let this_g_cost = cost_here.get(&current).unwrap_or(&0) + edge_cost;
            let mut add_this_as_parent = true;
            {
                let already_open_child = cost_here.get(&child);
                match already_open_child {
                    Some(&cost_prev) => if cost_prev <= this_g_cost { add_this_as_parent = false; },
                    None             => (),
                }
            }
            if add_this_as_parent {
                let this_f_cost = this_g_cost + heuristic(&child);
                parents.insert(child, current);
                open.push(State{cost: this_f_cost, node: child});
                cost_here.insert(child, this_g_cost);
            }
        }
    }

    if curr_backtrack_node.is_none() {
        return None;
    }

    loop {
        match curr_backtrack_node {
            None    => break,
            Some(n) => {
                ret.push(n);
                let parent = parents.get(&n);
                match parent {
                    None     => break,
                    Some(n2) => curr_backtrack_node = Some(*n2),
                }
            }
        }
    }
    ret.reverse();
    Some(ret)
}
<|endoftext|>


<commit_before>#![doc="Defines generic traits for numbers on which
SciRust library works.
"]

// Imports
use std::fmt::Show;

// complex numbers
use external::complex::{Complex32, Complex64};

/// Defines all the traits which a matrix element must support
pub trait Number : Num+Copy+Show {

    fn is_float() -> bool {
        false
    }

    fn is_int() -> bool {
        false
    }

    fn is_complex() -> bool {
        false
    }

    fn is_signed() -> bool;
}

/// Indicate that i8 fits all requirements for being a matrix element.
impl Number for i8 {

    #[inline]
    fn is_signed() -> bool {
        true
    }

}
/// Indicate that i16 fits all requirements for being a matrix element.
impl Number for i16 {

    #[inline]
    fn is_signed() -> bool {
        true
    }

    fn is_int() -> bool {
        true
    }

}
/// Indicate that i32 fits all requirements for being a matrix element.
impl Number for i32 {

    #[inline]
    fn is_signed() -> bool {
        true
    }

    fn is_int() -> bool {
        true
    }

}
/// Indicate that i64 fits all requirements for being a matrix element.
impl Number for i64 {

    #[inline]
    fn is_signed() -> bool {
        true
    }

    fn is_int() -> bool {
        true
    }

}

/// Indicate that int fits all requirements for being a matrix element.
impl Number for int {

    #[inline]
    fn is_signed() -> bool {
        true
    }

    fn is_int() -> bool {
        true
    }

}

/// Indicate that u8 fits all requirements for being a matrix element.
impl Number for u8 {

    #[inline]
    fn is_signed() -> bool {
        false
    }

    fn is_int() -> bool {
        true
    }

}
/// Indicate that u16 fits all requirements for being a matrix element.
impl Number for u16 {

    #[inline]
    fn is_signed() -> bool {
        false
    }

    fn is_int() -> bool {
        true
    }

}
/// Indicate that u32 fits all requirements for being a matrix element.
impl Number for u32 {

    #[inline]
    fn is_signed() -> bool {
        false
    }

    fn is_int() -> bool {
        true
    }

}

/// Indicate that u64 fits all requirements for being a matrix element.
impl Number for u64 {

    #[inline]
    fn is_signed() -> bool {
        false
    }

    fn is_int() -> bool {
        true
    }

}

/// Indicate that uint fits all requirements for being a matrix element.
impl Number for uint {

    #[inline]
    fn is_signed() -> bool {
        false
    }

    fn is_int() -> bool {
        true
    }

}

/// Indicate that f32 fits all requirements for being a matrix element.
impl Number for f32 {

    #[inline]
    fn is_signed() -> bool {
        true
    }

    fn is_float() -> bool {
        true
    }

}

/// Indicate that f64 fits all requirements for being a matrix element.
impl Number for f64 {

    #[inline]
    fn is_signed() -> bool {
        true
    }

    fn is_float() -> bool {
        true
    }

}

/// Indicate that Complex32 fits all requirements for being a matrix element.
impl Number for Complex32 {

    #[inline]
    fn is_signed() -> bool {
        true
    }

}

/// Indicate that Complex64 fits all requirements for being a matrix element.
impl Number for Complex64 {

    #[inline]
    fn is_signed() -> bool {
        true
    }

}

//TODO: figure out how to make this work.
//pub fn describe<T: Number>(){
    //println!("Signed: {}", T.is_signed());
//}
<commit_msg>Some work on Number template.<commit_after>#![doc="Defines generic traits for numbers on which
SciRust library works.
"]

// Imports
use std::fmt::Show;

// complex numbers
pub use external::complex::{Complex32, Complex64};

/// Defines all the traits which a matrix element must support
pub trait Number : Num+Copy+Show {

    #[inline]
    fn is_float(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        false
    }

    #[inline]
    fn is_complex(&self) -> bool {
        false
    }

    fn is_signed(&self) -> bool;
}

/// Indicate that i8 fits all requirements for being a matrix element.
impl Number for i8 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

}
/// Indicate that i16 fits all requirements for being a matrix element.
impl Number for i16 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}
/// Indicate that i32 fits all requirements for being a matrix element.
impl Number for i32 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}
/// Indicate that i64 fits all requirements for being a matrix element.
impl Number for i64 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/// Indicate that int fits all requirements for being a matrix element.
impl Number for int {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/// Indicate that u8 fits all requirements for being a matrix element.
impl Number for u8 {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}
/// Indicate that u16 fits all requirements for being a matrix element.
impl Number for u16 {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}
/// Indicate that u32 fits all requirements for being a matrix element.
impl Number for u32 {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/// Indicate that u64 fits all requirements for being a matrix element.
impl Number for u64 {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/// Indicate that uint fits all requirements for being a matrix element.
impl Number for uint {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/// Indicate that f32 fits all requirements for being a matrix element.
impl Number for f32 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_float(&self) -> bool {
        true
    }

}

/// Indicate that f64 fits all requirements for being a matrix element.
impl Number for f64 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_float(&self) -> bool {
        true
    }

}

/// Indicate that Complex32 fits all requirements for being a matrix element.
impl Number for Complex32 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_complex(&self) -> bool {
        true
    }

}

/// Indicate that Complex64 fits all requirements for being a matrix element.
impl Number for Complex64 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_complex(&self) -> bool {
        true
    }

}

//TODO: figure out how to make this work.
pub fn describe<T: Number>(z : T){
     println!("Signed: {}", z.is_signed());
}

/******************************************************
 *
 *   Unit tests follow.
 *
 *******************************************************/

#[cfg(test)]
mod tests {

    use super::*;
    use std::num::Zero;

    #[test]
    fn  test_introspection_i64(){
       let z : i64 = Zero::zero();
        describe(z);
        assert!(z.is_signed());
        assert!(!z.is_float());
        assert!(!z.is_complex());
        assert!(z.is_int());
    }

    #[test]
    fn  test_introspection_f64(){
       let z : f64 = Zero::zero();
        describe(z);
        assert!(z.is_signed());
        assert!(z.is_float());
        assert!(!z.is_complex());
        assert!(!z.is_int());
    }

    #[test]
    fn  test_introspection_c64(){
       let z : Complex64 = Zero::zero();
        describe(z);
        assert!(z.is_signed());
        assert!(!z.is_float());
        assert!(z.is_complex());
        assert!(!z.is_int());
    }

}<|endoftext|>


<commit_before>mod mmap_directory;
mod ram_directory;
mod directory;
mod read_only_source;
mod shared_vec_slice;
mod managed_directory;

/// Errors specific to the directory module.
pub mod error;

use std::io::{Write, Seek};

use std::io::BufWriter;
pub use self::read_only_source::ReadOnlySource;
pub use self::directory::Directory;
pub use self::ram_directory::RAMDirectory;
pub use self::mmap_directory::MmapDirectory;
pub use self::managed_directory::ManagedDirectory;

/// Synonym of Seek + Write
pub trait SeekableWrite: Seek + Write {}
impl<T: Seek + Write> SeekableWrite for T {}

/// Write object for Directory.
///
/// `WritePtr` are required to implement both Write
/// and Seek.
pub type WritePtr = BufWriter<Box<SeekableWrite>>;

#[cfg(test)]
mod tests {

    use super::*;
    use std::path::Path;
    use std::io::{Write, Seek, SeekFrom};

    lazy_static! {
        static ref TEST_PATH: &'static Path = Path::new("some_path_for_test");
    }

    #[test]
    fn test_ram_directory() {
        let mut ram_directory = RAMDirectory::create();
        test_directory(&mut ram_directory);
    }

    #[test]
    fn test_mmap_directory() {
        let mut mmap_directory = MmapDirectory::create_from_tempdir().unwrap();
        test_directory(&mut mmap_directory);
    }

    #[test]
    #[should_panic]
    fn ram_directory_panics_if_flush_forgotten() {
        let mut ram_directory = RAMDirectory::create();
        let mut write_file = ram_directory.open_write(*TEST_PATH).unwrap();
        assert!(write_file.write_all(&[4]).is_ok());
    }

    fn test_simple(directory: &mut Directory) {
        {
            let mut write_file = directory.open_write(*TEST_PATH).unwrap();
            assert!(directory.exists(*TEST_PATH));
            write_file.write_all(&[4]).unwrap();
            write_file.write_all(&[3]).unwrap();
            write_file.write_all(&[7,3,5]).unwrap();
            write_file.flush().unwrap();
        }
        let read_file = directory.open_read(*TEST_PATH).unwrap();
        let data: &[u8] = &*read_file;
        assert_eq!(data, &[4u8, 3u8, 7u8, 3u8, 5u8]);
        assert!(directory.delete(*TEST_PATH).is_ok());
        assert!(!directory.exists(*TEST_PATH));
    }

    fn test_seek(directory: &mut Directory) {
        {
            let mut write_file = directory.open_write(*TEST_PATH).unwrap();
            write_file.write_all(&[4, 3, 7,3,5]).unwrap();
            write_file.seek(SeekFrom::Start(0)).unwrap();
            write_file.write_all(&[3,1]).unwrap();
            write_file.flush().unwrap();
        }
        let read_file = directory.open_read(*TEST_PATH).unwrap();
        let data: &[u8] = &*read_file;
        assert_eq!(data, &[3u8, 1u8, 7u8, 3u8, 5u8]);
        assert!(directory.delete(*TEST_PATH).is_ok());
    }

    fn test_rewrite_forbidden(directory: &mut Directory) {
        {
            directory.open_write(*TEST_PATH).unwrap();
            assert!(directory.exists(*TEST_PATH));

        }
        {
            assert!(directory.open_write(*TEST_PATH).is_err());
        }
        assert!(directory.delete(*TEST_PATH).is_ok());
    }

    fn test_write_create_the_file(directory: &mut Directory) {
        {
            assert!(directory.open_read(*TEST_PATH).is_err());
            let _w = directory.open_write(*TEST_PATH).unwrap();
            assert!(directory.exists(*TEST_PATH));
            if let Err(e) = directory.open_read(*TEST_PATH) {
                println!("{:?}", e);
            }
            assert!(directory.open_read(*TEST_PATH).is_ok());
            assert!(directory.delete(*TEST_PATH).is_ok());
        }
    }

    fn test_directory_delete(directory: &mut Directory) {
        assert!(directory.open_read(*TEST_PATH).is_err());
        let mut write_file = directory.open_write(*TEST_PATH).unwrap();
        write_file.write_all(&[1, 2, 3, 4]).unwrap();
        write_file.flush().unwrap();
        let read_handle = directory.open_read(*TEST_PATH).unwrap();
        {
            assert_eq!(&*read_handle, &[1u8, 2u8, 3u8, 4u8]);
            assert!(directory.delete(*TEST_PATH).is_ok());
            assert!(directory.delete(Path::new("SomeOtherPath")).is_err());
            assert_eq!(&*read_handle, &[1u8, 2u8, 3u8, 4u8]);
        }
        assert!(directory.open_read(*TEST_PATH).is_err());
    }

    fn test_directory(directory: &mut Directory) {
        test_simple(directory);
        test_seek(directory);
        test_rewrite_forbidden(directory);
        test_write_create_the_file(directory);
        test_directory_delete(directory);
    }

}
<commit_msg>Delay deleting the files in the test suite to make it work on Windows<commit_after>mod mmap_directory;
mod ram_directory;
mod directory;
mod read_only_source;
mod shared_vec_slice;
mod managed_directory;

/// Errors specific to the directory module.
pub mod error;

use std::io::{Write, Seek};

use std::io::BufWriter;
pub use self::read_only_source::ReadOnlySource;
pub use self::directory::Directory;
pub use self::ram_directory::RAMDirectory;
pub use self::mmap_directory::MmapDirectory;
pub use self::managed_directory::ManagedDirectory;

/// Synonym of Seek + Write
pub trait SeekableWrite: Seek + Write {}
impl<T: Seek + Write> SeekableWrite for T {}

/// Write object for Directory.
///
/// `WritePtr` are required to implement both Write
/// and Seek.
pub type WritePtr = BufWriter<Box<SeekableWrite>>;

#[cfg(test)]
mod tests {

    use super::*;
    use std::path::Path;
    use std::io::{Write, Seek, SeekFrom};

    lazy_static! {
        static ref TEST_PATH: &'static Path = Path::new("some_path_for_test");
    }

    #[test]
    fn test_ram_directory() {
        let mut ram_directory = RAMDirectory::create();
        test_directory(&mut ram_directory);
    }

    #[test]
    fn test_mmap_directory() {
        let mut mmap_directory = MmapDirectory::create_from_tempdir().unwrap();
        test_directory(&mut mmap_directory);
    }

    #[test]
    #[should_panic]
    fn ram_directory_panics_if_flush_forgotten() {
        let mut ram_directory = RAMDirectory::create();
        let mut write_file = ram_directory.open_write(*TEST_PATH).unwrap();
        assert!(write_file.write_all(&[4]).is_ok());
    }

    fn test_simple(directory: &mut Directory) {
        {
            {
                let mut write_file = directory.open_write(*TEST_PATH).unwrap();
                assert!(directory.exists(*TEST_PATH));
                write_file.write_all(&[4]).unwrap();
                write_file.write_all(&[3]).unwrap();
                write_file.write_all(&[7,3,5]).unwrap();
                write_file.flush().unwrap();
            }
            let read_file = directory.open_read(*TEST_PATH).unwrap();
            let data: &[u8] = &*read_file;
            assert_eq!(data, &[4u8, 3u8, 7u8, 3u8, 5u8]);
        }

        assert!(directory.delete(*TEST_PATH).is_ok());
        assert!(!directory.exists(*TEST_PATH));
    }

    fn test_seek(directory: &mut Directory) {
        {
            {
                let mut write_file = directory.open_write(*TEST_PATH).unwrap();
                write_file.write_all(&[4, 3, 7,3,5]).unwrap();
                write_file.seek(SeekFrom::Start(0)).unwrap();
                write_file.write_all(&[3,1]).unwrap();
                write_file.flush().unwrap();
            }
            let read_file = directory.open_read(*TEST_PATH).unwrap();
            let data: &[u8] = &*read_file;
            assert_eq!(data, &[3u8, 1u8, 7u8, 3u8, 5u8]);
        }

        assert!(directory.delete(*TEST_PATH).is_ok());
    }

    fn test_rewrite_forbidden(directory: &mut Directory) {
        {
            directory.open_write(*TEST_PATH).unwrap();
            assert!(directory.exists(*TEST_PATH));

        }
        {
            assert!(directory.open_write(*TEST_PATH).is_err());
        }
        assert!(directory.delete(*TEST_PATH).is_ok());
    }

    fn test_write_create_the_file(directory: &mut Directory) {
        {
            assert!(directory.open_read(*TEST_PATH).is_err());
            let _w = directory.open_write(*TEST_PATH).unwrap();
            assert!(directory.exists(*TEST_PATH));
            if let Err(e) = directory.open_read(*TEST_PATH) {
                println!("{:?}", e);
            }
            assert!(directory.open_read(*TEST_PATH).is_ok());
            assert!(directory.delete(*TEST_PATH).is_ok());
        }
    }

    fn test_directory_delete(directory: &mut Directory) {
        assert!(directory.open_read(*TEST_PATH).is_err());
        let mut write_file = directory.open_write(*TEST_PATH).unwrap();
        write_file.write_all(&[1, 2, 3, 4]).unwrap();
        write_file.flush().unwrap();
        {
            let read_handle = directory.open_read(*TEST_PATH).unwrap();
            {
                assert_eq!(&*read_handle, &[1u8, 2u8, 3u8, 4u8]);

                // Mapped files can't be deleted on Windows
                if !cfg!(windows) {
                    assert!(directory.delete(*TEST_PATH).is_ok());
                    assert_eq!(&*read_handle, &[1u8, 2u8, 3u8, 4u8]);
                }

                assert!(directory.delete(Path::new("SomeOtherPath")).is_err());
            }
        }

        assert!(directory.delete(*TEST_PATH).is_ok());
        assert!(directory.open_read(*TEST_PATH).is_err());
        assert!(directory.delete(*TEST_PATH).is_err());
    }

    fn test_directory(directory: &mut Directory) {
        test_simple(directory);
        test_seek(directory);
        test_rewrite_forbidden(directory);
        test_write_create_the_file(directory);
        test_directory_delete(directory);
    }

}
<|endoftext|>


<commit_before>//! The driver trait which all drivers will implement.

use schema::Definition;
use error::{Error, ErrorCode};
use patch::Patch;
use value::{Pointer, Value};
use query::Query;

pub trait Driver {
  /// Connects to a driver and returns a driver instance. After calling this
  /// the driver is ready to roll!
  fn connect(uri: &str) -> Result<Box<Self>, Error>;

  /// Validates an Ardite Schema Definition dependending on the driver’s
  /// contracts with the developer. Note that the definition object will not be
  /// associated with the driver object. This is intentional, the driver should
  /// not be able to influence the definition without an external tool.
  fn validate_definition(_: &Definition) -> Result<(), Error> {
    Ok(())
  }

  /// Performs a complex query on the driver. Returns a value whose shape
  /// matches the shape of the query.
  fn query(&self, query: Query) -> Result<Value, Error>;

  /// Applies multiple patches to the driver. If one patch fails, all other
  /// patches must also fail. Returns a value with all of the new patched
  /// values along with any driver generated values only.
  fn patch(&self, patch: Vec<Patch>) -> Result<Value, Error>;

  /// Get’s a value in the driver at a specific point and returns exactly that
  /// value.
  fn get(&self, pointer: Pointer) -> Result<Value, Error> {
    match try!(self.query(Query::from(pointer.clone()))).get(pointer) {
      Some(value) => Ok(value),
      None => Err(Error::new(ErrorCode::Internal, "Driver failed to return a value with the requested data.", None))
    }
  }

  /// Set a value at a certain point in the driver. Returns nothing.
  fn set(&self, pointer: Pointer, value: Value) -> Result<(), Error> {
    try!(self.patch(vec![Patch::Set(pointer, value)]));
    Ok(())
  }
}
<commit_msg>style: move query into own line<commit_after>//! The driver trait which all drivers will implement.

use schema::Definition;
use error::{Error, ErrorCode};
use patch::Patch;
use value::{Pointer, Value};
use query::Query;

pub trait Driver {
  /// Connects to a driver and returns a driver instance. After calling this
  /// the driver is ready to roll!
  fn connect(uri: &str) -> Result<Box<Self>, Error>;

  /// Validates an Ardite Schema Definition dependending on the driver’s
  /// contracts with the developer. Note that the definition object will not be
  /// associated with the driver object. This is intentional, the driver should
  /// not be able to influence the definition without an external tool.
  fn validate_definition(_: &Definition) -> Result<(), Error> {
    Ok(())
  }

  /// Performs a complex query on the driver. Returns a value whose shape
  /// matches the shape of the query.
  fn query(&self, query: Query) -> Result<Value, Error>;

  /// Applies multiple patches to the driver. If one patch fails, all other
  /// patches must also fail. Returns a value with all of the new patched
  /// values along with any driver generated values only.
  fn patch(&self, patch: Vec<Patch>) -> Result<Value, Error>;

  /// Get’s a value in the driver at a specific point and returns exactly that
  /// value.
  fn get(&self, pointer: Pointer) -> Result<Value, Error> {
    let query = Query::from(pointer.clone());
    match try!(self.query(query)).get(pointer) {
      Some(value) => Ok(value),
      None => Err(Error::new(ErrorCode::Internal, "Driver failed to return a value with the requested data.", None))
    }
  }

  /// Set a value at a certain point in the driver. Returns nothing.
  fn set(&self, pointer: Pointer, value: Value) -> Result<(), Error> {
    try!(self.patch(vec![Patch::Set(pointer, value)]));
    Ok(())
  }
}
<|endoftext|>