<commit_before>extern crate byteorder;
extern crate chrono;
extern crate rustc_serialize;
extern crate xml as xml_rs;

pub mod binary;
pub mod xml;
mod builder;

use chrono::{DateTime, UTC};
use chrono::format::ParseError as ChronoParseError;
use std::collections::BTreeMap;
use std::io::{Read, Seek, SeekFrom};
use std::io::Error as IoError;

#[derive(Clone, Debug, PartialEq)]
pub enum Plist {
    Array(Vec<Plist>),
    Dictionary(BTreeMap<String, Plist>),
    Boolean(bool),
    Data(Vec<u8>),
    Date(DateTime<UTC>),
    Real(f64),
    Integer(i64),
    String(String),
}

use rustc_serialize::base64::{STANDARD, ToBase64};
use rustc_serialize::json::Json as RustcJson;

impl Plist {
    pub fn from_events<T>(events: T) -> Result<Plist, ()>
        where T: IntoIterator<Item = ReadResult<PlistEvent>>
    {
        let iter = events.into_iter();
        let builder = builder::Builder::new(iter);

        match builder.build() {
            Ok(plist) => Ok(plist),
            Err(_) => Err(()),
        }
    }

    pub fn into_events(self) -> Vec<PlistEvent> {
        let mut events = Vec::new();
        self.into_events_inner(&mut events);
        events
    }

    fn into_events_inner(self, events: &mut Vec<PlistEvent>) {
        match self {
            Plist::Array(array) => {
                events.push(PlistEvent::StartArray(Some(array.len() as u64)));
                for value in array.into_iter() {
                    value.into_events_inner(events);
                }
                events.push(PlistEvent::EndArray);
            }
            Plist::Dictionary(dict) => {
                events.push(PlistEvent::StartDictionary(Some(dict.len() as u64)));
                for (key, value) in dict.into_iter() {
                    events.push(PlistEvent::StringValue(key));
                    value.into_events_inner(events);
                }
                events.push(PlistEvent::EndDictionary);
            }
            Plist::Boolean(value) => events.push(PlistEvent::BooleanValue(value)),
            Plist::Data(value) => events.push(PlistEvent::DataValue(value)),
            Plist::Date(value) => events.push(PlistEvent::DateValue(value)),
            Plist::Real(value) => events.push(PlistEvent::RealValue(value)),
            Plist::Integer(value) => events.push(PlistEvent::IntegerValue(value)),
            Plist::String(value) => events.push(PlistEvent::StringValue(value)),
        }
    }

    pub fn into_rustc_serialize_json(self) -> RustcJson {
        match self {
            Plist::Array(value) => {
                RustcJson::Array(value.into_iter().map(|p| p.into_rustc_serialize_json()).collect())
            }
            Plist::Dictionary(value) => {
                RustcJson::Object(value.into_iter()
                                       .map(|(k, v)| (k, v.into_rustc_serialize_json()))
                                       .collect())
            }
            Plist::Boolean(value) => RustcJson::Boolean(value),
            Plist::Data(value) => RustcJson::String(value.to_base64(STANDARD)),
            Plist::Date(value) => RustcJson::String(value.to_rfc3339()),
            Plist::Real(value) => RustcJson::F64(value),
            Plist::Integer(value) => RustcJson::I64(value),
            Plist::String(value) => RustcJson::String(value),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum PlistEvent {
    StartPlist,
    EndPlist,

    StartArray(Option<u64>),
    EndArray,

    StartDictionary(Option<u64>),
    EndDictionary,

    BooleanValue(bool),
    DataValue(Vec<u8>),
    DateValue(DateTime<UTC>),
    IntegerValue(i64),
    RealValue(f64),
    StringValue(String),
}

pub type ReadResult<T> = Result<T, ReadError>;

#[derive(Debug)]
pub enum ReadError {
    InvalidData,
    UnexpectedEof,
    UnsupportedType,
    Io(IoError),
}

impl From<IoError> for ReadError {
    fn from(io_error: IoError) -> ReadError {
        ReadError::Io(io_error)
    }
}

impl From<ChronoParseError> for ReadError {
    fn from(_: ChronoParseError) -> ReadError {
        ReadError::InvalidData
    }
}

pub struct EventReader<R: Read + Seek>(EventReaderInner<R>);

enum EventReaderInner<R: Read + Seek> {
    Uninitialized(Option<R>),
    Xml(xml::EventReader<R>),
    Binary(binary::EventReader<R>),
}

impl<R: Read + Seek> EventReader<R> {
    pub fn new(reader: R) -> EventReader<R> {
        EventReader(EventReaderInner::Uninitialized(Some(reader)))
    }

    fn is_binary(reader: &mut R) -> Result<bool, IoError> {
        try!(reader.seek(SeekFrom::Start(0)));
        let mut magic = [0; 8];
        try!(reader.read(&mut magic));
        try!(reader.seek(SeekFrom::Start(0)));

        Ok(if &magic == b"bplist00" {
            true
        } else {
            false
        })
    }
}

impl<R: Read + Seek> Iterator for EventReader<R> {
    type Item = ReadResult<PlistEvent>;

    fn next(&mut self) -> Option<ReadResult<PlistEvent>> {
        let mut reader = match self.0 {
            EventReaderInner::Xml(ref mut parser) => return parser.next(),
            EventReaderInner::Binary(ref mut parser) => return parser.next(),
            EventReaderInner::Uninitialized(ref mut reader) => reader.take().unwrap(),
        };

        let event_reader = match EventReader::is_binary(&mut reader) {
            Ok(true) => EventReaderInner::Binary(binary::EventReader::new(reader)),
            Ok(false) => EventReaderInner::Xml(xml::EventReader::new(reader)),
            Err(err) => {
                ::std::mem::replace(&mut self.0, EventReaderInner::Uninitialized(Some(reader)));
                return Some(Err(ReadError::Io(err)));
            }
        };

        ::std::mem::replace(&mut self.0, event_reader);

        self.next()
    }
}
<commit_msg>Add Plist::read utility method<commit_after>extern crate byteorder;
extern crate chrono;
extern crate rustc_serialize;
extern crate xml as xml_rs;

pub mod binary;
pub mod xml;
mod builder;

use chrono::{DateTime, UTC};
use chrono::format::ParseError as ChronoParseError;
use std::collections::BTreeMap;
use std::io::{Read, Seek, SeekFrom};
use std::io::Error as IoError;

#[derive(Clone, Debug, PartialEq)]
pub enum Plist {
    Array(Vec<Plist>),
    Dictionary(BTreeMap<String, Plist>),
    Boolean(bool),
    Data(Vec<u8>),
    Date(DateTime<UTC>),
    Real(f64),
    Integer(i64),
    String(String),
}

use rustc_serialize::base64::{STANDARD, ToBase64};
use rustc_serialize::json::Json as RustcJson;

impl Plist {
    pub fn read<R: Read + Seek>(reader: R) -> Result<Plist, ()> {
        let reader = EventReader::new(reader);
        Plist::from_events(reader)
    }

    pub fn from_events<T>(events: T) -> Result<Plist, ()>
        where T: IntoIterator<Item = ReadResult<PlistEvent>>
    {
        let iter = events.into_iter();
        let builder = builder::Builder::new(iter);

        match builder.build() {
            Ok(plist) => Ok(plist),
            Err(_) => Err(()),
        }
    }

    pub fn into_events(self) -> Vec<PlistEvent> {
        let mut events = Vec::new();
        self.into_events_inner(&mut events);
        events
    }

    fn into_events_inner(self, events: &mut Vec<PlistEvent>) {
        match self {
            Plist::Array(array) => {
                events.push(PlistEvent::StartArray(Some(array.len() as u64)));
                for value in array.into_iter() {
                    value.into_events_inner(events);
                }
                events.push(PlistEvent::EndArray);
            }
            Plist::Dictionary(dict) => {
                events.push(PlistEvent::StartDictionary(Some(dict.len() as u64)));
                for (key, value) in dict.into_iter() {
                    events.push(PlistEvent::StringValue(key));
                    value.into_events_inner(events);
                }
                events.push(PlistEvent::EndDictionary);
            }
            Plist::Boolean(value) => events.push(PlistEvent::BooleanValue(value)),
            Plist::Data(value) => events.push(PlistEvent::DataValue(value)),
            Plist::Date(value) => events.push(PlistEvent::DateValue(value)),
            Plist::Real(value) => events.push(PlistEvent::RealValue(value)),
            Plist::Integer(value) => events.push(PlistEvent::IntegerValue(value)),
            Plist::String(value) => events.push(PlistEvent::StringValue(value)),
        }
    }

    pub fn into_rustc_serialize_json(self) -> RustcJson {
        match self {
            Plist::Array(value) => {
                RustcJson::Array(value.into_iter().map(|p| p.into_rustc_serialize_json()).collect())
            }
            Plist::Dictionary(value) => {
                RustcJson::Object(value.into_iter()
                                       .map(|(k, v)| (k, v.into_rustc_serialize_json()))
                                       .collect())
            }
            Plist::Boolean(value) => RustcJson::Boolean(value),
            Plist::Data(value) => RustcJson::String(value.to_base64(STANDARD)),
            Plist::Date(value) => RustcJson::String(value.to_rfc3339()),
            Plist::Real(value) => RustcJson::F64(value),
            Plist::Integer(value) => RustcJson::I64(value),
            Plist::String(value) => RustcJson::String(value),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum PlistEvent {
    StartPlist,
    EndPlist,

    StartArray(Option<u64>),
    EndArray,

    StartDictionary(Option<u64>),
    EndDictionary,

    BooleanValue(bool),
    DataValue(Vec<u8>),
    DateValue(DateTime<UTC>),
    IntegerValue(i64),
    RealValue(f64),
    StringValue(String),
}

pub type ReadResult<T> = Result<T, ReadError>;

#[derive(Debug)]
pub enum ReadError {
    InvalidData,
    UnexpectedEof,
    UnsupportedType,
    Io(IoError),
}

impl From<IoError> for ReadError {
    fn from(io_error: IoError) -> ReadError {
        ReadError::Io(io_error)
    }
}

impl From<ChronoParseError> for ReadError {
    fn from(_: ChronoParseError) -> ReadError {
        ReadError::InvalidData
    }
}

pub struct EventReader<R: Read + Seek>(EventReaderInner<R>);

enum EventReaderInner<R: Read + Seek> {
    Uninitialized(Option<R>),
    Xml(xml::EventReader<R>),
    Binary(binary::EventReader<R>),
}

impl<R: Read + Seek> EventReader<R> {
    pub fn new(reader: R) -> EventReader<R> {
        EventReader(EventReaderInner::Uninitialized(Some(reader)))
    }

    fn is_binary(reader: &mut R) -> Result<bool, IoError> {
        try!(reader.seek(SeekFrom::Start(0)));
        let mut magic = [0; 8];
        try!(reader.read(&mut magic));
        try!(reader.seek(SeekFrom::Start(0)));

        Ok(if &magic == b"bplist00" {
            true
        } else {
            false
        })
    }
}

impl<R: Read + Seek> Iterator for EventReader<R> {
    type Item = ReadResult<PlistEvent>;

    fn next(&mut self) -> Option<ReadResult<PlistEvent>> {
        let mut reader = match self.0 {
            EventReaderInner::Xml(ref mut parser) => return parser.next(),
            EventReaderInner::Binary(ref mut parser) => return parser.next(),
            EventReaderInner::Uninitialized(ref mut reader) => reader.take().unwrap(),
        };

        let event_reader = match EventReader::is_binary(&mut reader) {
            Ok(true) => EventReaderInner::Binary(binary::EventReader::new(reader)),
            Ok(false) => EventReaderInner::Xml(xml::EventReader::new(reader)),
            Err(err) => {
                ::std::mem::replace(&mut self.0, EventReaderInner::Uninitialized(Some(reader)));
                return Some(Err(ReadError::Io(err)));
            }
        };

        ::std::mem::replace(&mut self.0, event_reader);

        self.next()
    }
}
<|endoftext|>


<commit_before>//! Complex numbers

#![deny(missing_docs, warnings)]

extern crate onezero;

use std::fmt;
use std::num::FloatMath;
use std::rand::{Rand, Rng};

use onezero::{One, Zero};

/// A complex number in Cartesian form.
#[repr(C)]
#[deriving(PartialEq)]
pub struct Complex<T> {
    /// The real part
    pub re: T,
    /// The imaginary part
    pub im: T,
}

#[allow(non_camel_case_types)]
pub type c64 = Complex<f32>;
#[allow(non_camel_case_types)]
pub type c128 = Complex<f64>;

impl<T> Complex<T> {
    /// Create a new complex number
    pub fn new(re: T, im: T) -> Complex<T> {
        Complex {
            im: im,
            re: re,
        }
    }
}

impl<T> Complex<T> where T: Clone + Neg<T> {
    /// Returns the complex conjugate
    pub fn conj(&self) -> Complex<T> {
        Complex {
            re: self.re.clone(),
            im: -self.im,
        }
    }
}

impl<T> Complex<T> where T: Add<T, T> + Mul<T, T> {
    /// Returns the square of the norm
    pub fn norm_sqr(&self) -> T {
        self.re * self.re + self.im * self.im
    }
}

impl<T> Complex<T> where T: FloatMath {
    /// Returns the absolute value
    pub fn abs(&self) -> T {
        self.re.hypot(self.im)
    }

    /// Returns the argument
    pub fn arg(&self) -> T {
        self.im.atan2(self.re)
    }
}

impl<T> Add<T, Complex<T>> for Complex<T> where T: Add<T, T> + Clone {
    fn add(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.add(rhs),
            im: self.im.clone(),
        }
    }
}

impl<T> Add<Complex<T>, Complex<T>> for Complex<T> where T: Add<T, T> {
    fn add(&self, rhs: &Complex<T>) -> Complex<T> {
        Complex {
            re: self.re + rhs.re,
            im: self.im + rhs.im,
        }
    }
}

impl<T> Div<T, Complex<T>> for Complex<T> where T: Div<T, T> {
    fn div(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.div(rhs),
            im: self.im.div(rhs),
        }
    }
}

impl<T> Div<Complex<T>, Complex<T>> for Complex<T> where
    T: Add<T, T> + Div<T, T> + Mul<T, T> + Sub<T, T>
{
    fn div(&self, rhs: &Complex<T>) -> Complex<T> {
        let den = rhs.norm_sqr();

        Complex {
            re: (self.re * rhs.re + self.im + rhs.im) / den,
            im: (self.im * rhs.re - self.re * rhs.im) / den,
        }
    }
}

impl<T> Mul<T, Complex<T>> for Complex<T> where T: Mul<T, T> {
    fn mul(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.mul(rhs),
            im: self.im.mul(rhs),
        }
    }
}

impl<T> Mul<Complex<T>, Complex<T>> for Complex<T> where T: Add<T, T> + Mul<T, T> + Sub<T, T> {
    fn mul(&self, rhs: &Complex<T>) -> Complex<T> {
        Complex {
            re: self.re * rhs.re - self.im * rhs.im,
            im: self.re * rhs.im + self.im * rhs.re,
        }
    }
}

impl<T> Neg<Complex<T>> for Complex<T> where T: Neg<T> {
    fn neg(&self) -> Complex<T> {
        Complex {
            re: self.re.neg(),
            im: self.im.neg(),
        }
    }
}

impl<T> One for Complex<T> where T: Mul<T, T> + One + Sub<T, T> + Zero {
    fn one() -> Complex<T> {
        Complex {
            re: One::one(),
            im: Zero::zero(),
        }
    }
}

impl<T> Rand for Complex<T> where T: Rand {
    fn rand<R>(rng: &mut R) -> Complex<T> where R: Rng {
        Complex::new(rng.gen(), rng.gen())
    }
}

impl<T> fmt::Show for Complex<T> where T: PartialOrd + fmt::Show + Zero {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < Zero::zero() {
            write!(f, "{}-{}i", self.re, self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}

impl<T> Sub<T, Complex<T>> for Complex<T> where T: Clone + Sub<T, T> {
    fn sub(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.sub(rhs),
            im: self.im.clone(),
        }
    }
}

impl<T> Sub<Complex<T>, Complex<T>> for Complex<T> where T: Sub<T, T> {
    fn sub(&self, rhs: &Complex<T>) -> Complex<T> {
        Complex {
            re: self.re - rhs.re,
            im: self.im - rhs.im,
        }
    }
}

impl<T> Zero for Complex<T> where T: Zero {
    fn zero() -> Complex<T> {
        Complex {
            re: Zero::zero(),
            im: Zero::zero(),
        }
    }
}
<commit_msg>feat(Complex): implement commutative `Add`/`Mul` between `Complex<T>` and `T`<commit_after>//! Complex numbers

#![deny(missing_docs, warnings)]

extern crate onezero;

use std::fmt;
use std::num::FloatMath;
use std::rand::{Rand, Rng};

use onezero::{One, Zero};

/// A complex number in Cartesian form.
#[repr(C)]
#[deriving(PartialEq)]
pub struct Complex<T> {
    /// The real part
    pub re: T,
    /// The imaginary part
    pub im: T,
}

#[allow(non_camel_case_types)]
pub type c64 = Complex<f32>;
#[allow(non_camel_case_types)]
pub type c128 = Complex<f64>;

impl<T> Complex<T> {
    /// Create a new complex number
    pub fn new(re: T, im: T) -> Complex<T> {
        Complex {
            im: im,
            re: re,
        }
    }
}

impl<T> Complex<T> where T: Clone + Neg<T> {
    /// Returns the complex conjugate
    pub fn conj(&self) -> Complex<T> {
        Complex {
            re: self.re.clone(),
            im: -self.im,
        }
    }
}

impl<T> Complex<T> where T: Add<T, T> + Mul<T, T> {
    /// Returns the square of the norm
    pub fn norm_sqr(&self) -> T {
        self.re * self.re + self.im * self.im
    }
}

impl<T> Complex<T> where T: FloatMath {
    /// Returns the absolute value
    pub fn abs(&self) -> T {
        self.re.hypot(self.im)
    }

    /// Returns the argument
    pub fn arg(&self) -> T {
        self.im.atan2(self.re)
    }
}

impl<T> Add<T, Complex<T>> for Complex<T> where T: Add<T, T> + Clone {
    fn add(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.add(rhs),
            im: self.im.clone(),
        }
    }
}

impl<T> Add<Complex<T>, Complex<T>> for Complex<T> where T: Add<T, T> {
    fn add(&self, rhs: &Complex<T>) -> Complex<T> {
        Complex {
            re: self.re + rhs.re,
            im: self.im + rhs.im,
        }
    }
}

impl<T> Add<Complex<T>, Complex<T>> for T where T: Add<T, T> + Clone {
    fn add(&self, rhs: &Complex<T>) -> Complex<T> {
        rhs.add(self)
    }
}

impl<T> Div<T, Complex<T>> for Complex<T> where T: Div<T, T> {
    fn div(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.div(rhs),
            im: self.im.div(rhs),
        }
    }
}

impl<T> Div<Complex<T>, Complex<T>> for Complex<T> where
    T: Add<T, T> + Div<T, T> + Mul<T, T> + Sub<T, T>
{
    fn div(&self, rhs: &Complex<T>) -> Complex<T> {
        let den = rhs.norm_sqr();

        Complex {
            re: (self.re * rhs.re + self.im + rhs.im) / den,
            im: (self.im * rhs.re - self.re * rhs.im) / den,
        }
    }
}

impl<T> Mul<T, Complex<T>> for Complex<T> where T: Mul<T, T> {
    fn mul(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.mul(rhs),
            im: self.im.mul(rhs),
        }
    }
}

impl<T> Mul<Complex<T>, Complex<T>> for Complex<T> where T: Add<T, T> + Mul<T, T> + Sub<T, T> {
    fn mul(&self, rhs: &Complex<T>) -> Complex<T> {
        Complex {
            re: self.re * rhs.re - self.im * rhs.im,
            im: self.re * rhs.im + self.im * rhs.re,
        }
    }
}

impl<T> Mul<Complex<T>, Complex<T>> for T where T: Mul<T, T> {
    fn mul(&self, rhs: &Complex<T>) -> Complex<T> {
        rhs.mul(self)
    }
}

impl<T> Neg<Complex<T>> for Complex<T> where T: Neg<T> {
    fn neg(&self) -> Complex<T> {
        Complex {
            re: self.re.neg(),
            im: self.im.neg(),
        }
    }
}

impl<T> One for Complex<T> where T: Mul<T, T> + One + Sub<T, T> + Zero {
    fn one() -> Complex<T> {
        Complex {
            re: One::one(),
            im: Zero::zero(),
        }
    }
}

impl<T> Rand for Complex<T> where T: Rand {
    fn rand<R>(rng: &mut R) -> Complex<T> where R: Rng {
        Complex::new(rng.gen(), rng.gen())
    }
}

impl<T> fmt::Show for Complex<T> where T: PartialOrd + fmt::Show + Zero {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < Zero::zero() {
            write!(f, "{}-{}i", self.re, self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}

impl<T> Sub<T, Complex<T>> for Complex<T> where T: Clone + Sub<T, T> {
    fn sub(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.sub(rhs),
            im: self.im.clone(),
        }
    }
}

impl<T> Sub<Complex<T>, Complex<T>> for Complex<T> where T: Sub<T, T> {
    fn sub(&self, rhs: &Complex<T>) -> Complex<T> {
        Complex {
            re: self.re - rhs.re,
            im: self.im - rhs.im,
        }
    }
}

impl<T> Zero for Complex<T> where T: Zero {
    fn zero() -> Complex<T> {
        Complex {
            re: Zero::zero(),
            im: Zero::zero(),
        }
    }
}
<|endoftext|>


<commit_before>//! A library for creating and modifying Tree structures.
//!
//! # Overview
//! In this implementation, the `Tree` owns all of the `Node`s and all inter-`Node` relationships
//! are managed with `NodeId`s.
//!
//! `Tree`s in this library are "just" trees.  They do not allow cycles.  They do not allow
//! the creation of arbitrary Graph structures.  There is no weight associated with edges between
//! `Node`s.  In addition, each `Node` can have an arbitrary number of child `Node`s.
//!
//! It is important to note that this library does not support comparison-based `Node` insertion.
//! In other words, this is not a Binary Search Tree (or any other kind of search tree) library.
//! It is purely a library for storing data in a hierarchical manner.  The caller must know the
//! structure that they wish to build and then use this library to do so;  this library will not
//! make those structural decisions for you.
//!
//! ## Example Usage
//! ```
//! use id_tree::*;
//!
//! fn main() {
//!     use id_tree::InsertBehavior::*;
//!
//!     //      0
//!     //     / \
//!     //    1   2
//!     //   / \
//!     //  3   4
//!     let mut tree: Tree<i32> = TreeBuilder::new()
//!         .with_node_capacity(5)
//!         .build();
//!
//!     let root_id: NodeId = tree.insert(Node::new(0), AsRoot).unwrap();
//!     let child_id: NodeId = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
//!     tree.insert(Node::new(2), UnderNode(&root_id)).unwrap();
//!     tree.insert(Node::new(3), UnderNode(&child_id)).unwrap();
//!     tree.insert(Node::new(4), UnderNode(&child_id)).unwrap();
//!
//!     println!("Pre-order:");
//!     print_pre_order(&tree, &root_id);
//!     // results in the output "0, 1, 3, 4, 2, "
//! }
//!
//! fn print_pre_order(tree: &Tree<i32>, node_id: &NodeId) {
//!     let node_ref = tree.get(node_id).unwrap();
//!
//!     print!("{}, ", node_ref.data());
//!
//!     for child_id in node_ref.children() {
//!         print_pre_order(tree, &child_id);
//!     }
//! }
//! ```
//!
//! ## Project Goals
//! * Allow caller control of as many allocations as possible (through pre-allocation)
//! * Fast `Node` insertion and removal
//! * Arbitrary _Tree_ structure creation and manipulation
//!
//! ## Non-Goals
//! * Arbitrary _Graph_ structure creation and manipulation
//! * Comparison-based node insertion of any kind
//!
//! #### Drawbacks of this Library
//! Sadly, Rust's ownership/reference system is sidestepped a bit by this implementation and this
//! can cause issues if the caller doesn't pay attention to what they are doing with `NodeId`s.
//!
//! We try to solve these issues with very careful usage of `NodeId`s so that the caller doesn't
//! have to be bothered (too much) with these concerns.
//!
//! Please see the [Potential `NodeId` Issues](struct.NodeId.html#potential-nodeid-issues) section
//! of the `NodeId` documentation for more info on what these issues are and how this library
//! attempts to solve them.
//!

extern crate snowflake;
use self::snowflake::ProcessUniqueId;

mod behaviors;
mod error;
mod node;
mod tree;

pub use behaviors::RemoveBehavior;
pub use behaviors::MoveBehavior;
pub use behaviors::InsertBehavior;
pub use behaviors::SwapBehavior;
pub use error::NodeIdError;
pub use node::NodeBuilder;
pub use node::Node;
pub use tree::TreeBuilder;
pub use tree::Tree;
pub use tree::iterators::Ancestors;
pub use tree::iterators::AncestorIds;
pub use tree::iterators::Children;
pub use tree::iterators::ChildrenIds;
pub use tree::iterators::PreOrderTraversal;
pub use tree::iterators::PostOrderTraversal;

///
/// An identifier used to differentiate between `Node`s within a `Tree`.
///
/// `NodeId`s are not something that the calling context will ever have to worry about generating.
/// `Tree`s generate `NodeId`s as `Node`s are inserted into them.
///
/// In addition, each `NodeId` is specific to the `Tree` that generated it.  This means that if
/// there are two `Tree`s - `A` and `B` - there's no worry of trying to access a `Node` in `A` with
/// an identifier that came from `B`.  Doing so will return a `Result::Err` value instead of
/// returning the wrong `Node`.
///
/// #### Potential `NodeId` Issues
///
/// Because `Tree`s pass out `NodeId`s as `Node`s are inserted, several issues can occur:
///
/// 1. If a `Node` is removed, the `NodeId` that previously identified it now points to nothing
/// (technically a `None` value in this case).
/// 2. If a `Node` is removed and then another is inserted later, the "new" `NodeId` that is
/// returned can (and will) be the same `NodeId` that was used to identify a different `Node`
/// previously.
///
/// The above issues may seem like deal-breakers, but our situation isn't as bad as it seems:
///
/// The first issue can be easily detected by the library itself.  In this situation, a
/// `Result::Err` will be returned with the appropriate `NodeIdError`. The second issue, however, is
/// not something that the library can detect. To mitigate this problem, this library ensures the
/// following:
///
/// 1. All `Node` methods that provide `NodeId`s will **return** `&NodeId`s instead of `NodeId`s.
/// 2. All `Tree` methods that **read** or **insert** data accept `&NodeId`s instead of taking
/// `NodeId`s.
/// 3. All `Tree` methods that **remove** data take `NodeId`s instead of accepting `&NodeId`s.
/// 4. All `Node`s that have been removed from a `Tree` will have their parent and child references
/// cleared (to avoid leaking extra `NodeId` copies).
/// 5. `NodeId`s themselves are `Clone`, but not `Copy`.
///
/// This means that no methods will ever take ownership of a `NodeId` except for methods that remove
/// a `Node` from a `Tree`. The resulting behavior is that unless the caller **explicitly `Clone`s a
/// `NodeId`** they should never be in a situation where they accidentally hold onto a `NodeId` too
/// long.  This means that we have "almost safe references" that the caller can clone if they choose
/// to.  Doing so, however, will open up the possibility of confusing which `NodeId`s refer to which
/// `Node`s in the calling context.
///
/// This _does_ transfer some of the burden to the caller, but any errors should be fairly easy to
/// sort out because an explicit `Clone` is required for such an error to occur.
///
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub struct NodeId {
    tree_id: ProcessUniqueId,
    index: usize,
}

trait MutableNode {
    fn set_parent(&mut self, parent: Option<NodeId>);
    fn add_child(&mut self, child: NodeId);
    fn replace_child(&mut self, old: NodeId, new: NodeId);
    fn children_mut(&mut self) -> &mut Vec<NodeId>;
    fn set_children(&mut self, children: Vec<NodeId>);
    fn take_children(&mut self) -> Vec<NodeId>;
}
<commit_msg>update docs example<commit_after>//! A library for creating and modifying Tree structures.
//!
//! # Overview
//! In this implementation, the `Tree` owns all of the `Node`s and all inter-`Node` relationships
//! are managed with `NodeId`s.
//!
//! `Tree`s in this library are "just" trees.  They do not allow cycles.  They do not allow
//! the creation of arbitrary Graph structures.  There is no weight associated with edges between
//! `Node`s.  In addition, each `Node` can have an arbitrary number of child `Node`s.
//!
//! It is important to note that this library does not support comparison-based `Node` insertion.
//! In other words, this is not a Binary Search Tree (or any other kind of search tree) library.
//! It is purely a library for storing data in a hierarchical manner.  The caller must know the
//! structure that they wish to build and then use this library to do so;  this library will not
//! make those structural decisions for you.
//!
//! ## Example Usage
//! ```
//! use id_tree::*;
//!
//! fn main() {
//!     use id_tree::InsertBehavior::*;
//!
//!     //      0
//!     //     / \
//!     //    1   2
//!     //   / \
//!     //  3   4
//!     let mut tree: Tree<i32> = TreeBuilder::new()
//!         .with_node_capacity(5)
//!         .build();
//!
//!     let root_id: NodeId = tree.insert(Node::new(0), AsRoot).unwrap();
//!     let child_id: NodeId = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
//!     tree.insert(Node::new(2), UnderNode(&root_id)).unwrap();
//!     tree.insert(Node::new(3), UnderNode(&child_id)).unwrap();
//!     tree.insert(Node::new(4), UnderNode(&child_id)).unwrap();
//!
//!     println!("Post-order:");
//!     for node in tree.traverse_pre_order(&root_id).unwrap() {
//!         print!("{}, ", node.data());
//!     }
//!     // results in the output "0, 1, 3, 4, 2, "
//! }
//! ```
//!
//! ## Project Goals
//! * Allow caller control of as many allocations as possible (through pre-allocation)
//! * Fast `Node` insertion and removal
//! * Arbitrary _Tree_ structure creation and manipulation
//!
//! ## Non-Goals
//! * Arbitrary _Graph_ structure creation and manipulation
//! * Comparison-based node insertion of any kind
//!
//! #### Drawbacks of this Library
//! Sadly, Rust's ownership/reference system is sidestepped a bit by this implementation and this
//! can cause issues if the caller doesn't pay attention to what they are doing with `NodeId`s.
//!
//! We try to solve these issues with very careful usage of `NodeId`s so that the caller doesn't
//! have to be bothered (too much) with these concerns.
//!
//! Please see the [Potential `NodeId` Issues](struct.NodeId.html#potential-nodeid-issues) section
//! of the `NodeId` documentation for more info on what these issues are and how this library
//! attempts to solve them.
//!

extern crate snowflake;
use self::snowflake::ProcessUniqueId;

mod behaviors;
mod error;
mod node;
mod tree;

pub use behaviors::RemoveBehavior;
pub use behaviors::MoveBehavior;
pub use behaviors::InsertBehavior;
pub use behaviors::SwapBehavior;
pub use error::NodeIdError;
pub use node::NodeBuilder;
pub use node::Node;
pub use tree::TreeBuilder;
pub use tree::Tree;
pub use tree::iterators::Ancestors;
pub use tree::iterators::AncestorIds;
pub use tree::iterators::Children;
pub use tree::iterators::ChildrenIds;
pub use tree::iterators::PreOrderTraversal;
pub use tree::iterators::PostOrderTraversal;

///
/// An identifier used to differentiate between `Node`s within a `Tree`.
///
/// `NodeId`s are not something that the calling context will ever have to worry about generating.
/// `Tree`s generate `NodeId`s as `Node`s are inserted into them.
///
/// In addition, each `NodeId` is specific to the `Tree` that generated it.  This means that if
/// there are two `Tree`s - `A` and `B` - there's no worry of trying to access a `Node` in `A` with
/// an identifier that came from `B`.  Doing so will return a `Result::Err` value instead of
/// returning the wrong `Node`.
///
/// #### Potential `NodeId` Issues
///
/// Because `Tree`s pass out `NodeId`s as `Node`s are inserted, several issues can occur:
///
/// 1. If a `Node` is removed, the `NodeId` that previously identified it now points to nothing
/// (technically a `None` value in this case).
/// 2. If a `Node` is removed and then another is inserted later, the "new" `NodeId` that is
/// returned can (and will) be the same `NodeId` that was used to identify a different `Node`
/// previously.
///
/// The above issues may seem like deal-breakers, but our situation isn't as bad as it seems:
///
/// The first issue can be easily detected by the library itself.  In this situation, a
/// `Result::Err` will be returned with the appropriate `NodeIdError`. The second issue, however, is
/// not something that the library can detect. To mitigate this problem, this library ensures the
/// following:
///
/// 1. All `Node` methods that provide `NodeId`s will **return** `&NodeId`s instead of `NodeId`s.
/// 2. All `Tree` methods that **read** or **insert** data accept `&NodeId`s instead of taking
/// `NodeId`s.
/// 3. All `Tree` methods that **remove** data take `NodeId`s instead of accepting `&NodeId`s.
/// 4. All `Node`s that have been removed from a `Tree` will have their parent and child references
/// cleared (to avoid leaking extra `NodeId` copies).
/// 5. `NodeId`s themselves are `Clone`, but not `Copy`.
///
/// This means that no methods will ever take ownership of a `NodeId` except for methods that remove
/// a `Node` from a `Tree`. The resulting behavior is that unless the caller **explicitly `Clone`s a
/// `NodeId`** they should never be in a situation where they accidentally hold onto a `NodeId` too
/// long.  This means that we have "almost safe references" that the caller can clone if they choose
/// to.  Doing so, however, will open up the possibility of confusing which `NodeId`s refer to which
/// `Node`s in the calling context.
///
/// This _does_ transfer some of the burden to the caller, but any errors should be fairly easy to
/// sort out because an explicit `Clone` is required for such an error to occur.
///
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub struct NodeId {
    tree_id: ProcessUniqueId,
    index: usize,
}

trait MutableNode {
    fn set_parent(&mut self, parent: Option<NodeId>);
    fn add_child(&mut self, child: NodeId);
    fn replace_child(&mut self, old: NodeId, new: NodeId);
    fn children_mut(&mut self) -> &mut Vec<NodeId>;
    fn set_children(&mut self, children: Vec<NodeId>);
    fn take_children(&mut self) -> Vec<NodeId>;
}
<|endoftext|>


<commit_before>use chrono::{serde::ts_nanoseconds, DateTime, Duration, Utc};
use serde::{Deserialize, Serialize};

/// Structure that contains information for a scheduled program
#[derive(Debug, Serialize, Deserialize)]
pub struct Program {
    /// Unique id for the program
    id: String,
    /// The title of the program
    title: String,
    /// List of categories that applies to the program
    categories: Vec<String>,
    /// Returns whether this is available as a VOD
    #[serde(rename = "availableAsVod")]
    available_as_vod: bool,
    /// Returns whether this is a rerun
    rerun: bool,
    /// Returns whether this is a premiering episode
    premiere: bool,
    /// Returns whether this is a live program
    live: bool,
    /// The time the program starts, as UTC time.
    #[serde(rename = "start", with = "ts_nanoseconds")]
    starts_at: DateTime<Utc>,
    /// The time the program ends, as UTC time.
    #[serde(rename = "stop", with = "ts_nanoseconds")]
    ends_at: DateTime<Utc>,
}

impl Program {
    pub fn duration(&self) -> Duration {
        self.ends_at - self.starts_at
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Channel {
    /// The unique ID of the channel
    id: String,
    /// The name of the channel
    title: String,
    /// An url to an icon for the channel
    icon: String,
    /// An url to a logo for the channel
    logo: String,
    /// An url to a logo for the channel in SVG format
    #[serde(rename = "svgLogo")]
    svg_logo: String,
    /// Sorting index
    sort: u32,
}

#[cfg(test)]
mod tests {
    use super::*;
    use rstest::*;

    #[fixture]
    fn program() -> Program {
        let json = r#"
            {
              "stop": 1585458000,
              "start": 1585454700,
              "categories": [
                "Kultur og Natur",
                "Programmer"
              ],
              "id": "20605495",
              "title": "Fantastiske floder: Mississippifloden",
              "availableAsVod": false,
              "rerun": true,
              "premiere": false,
              "live": false
            }
        "#;

        serde_json::from_str(&json).unwrap()
    }

    #[fixture]
    fn channel() -> Channel {
        let json = r#"
            {
              "id": "1",
              "title": "DR1",
              "icon": "https://epg-images.tv2.dk/channellogos/icon/1.png",
              "logo": "https://epg-images.tv2.dk/channellogos/logo/1.png",
              "svgLogo": "https://epg-images.tv2.dk/channellogos/svg/1.svg",
              "sort": 1
            }
        "#;

        serde_json::from_str(&json).unwrap()
    }

    #[rstest]
    fn it_deserializes_program(program: Program) {
        assert_eq!(program.title, "Fantastiske floder: Mississippifloden");
        assert_eq!(program.id, "20605495");
        assert_eq!(program.available_as_vod, false);
        assert!(program.rerun);
        assert_eq!(program.premiere, false);
        assert_eq!(program.live, false);
        assert!(program.categories.len() > 0);
    }

    #[rstest]
    fn it_deserializes_channel(channel: Channel) {
        assert_eq!(channel.id, "1");
        assert_eq!(channel.title, "DR1");
        assert!(!channel.icon.is_empty());
        assert!(!channel.logo.is_empty());
        assert!(!channel.svg_logo.is_empty());
    }

    #[rstest]
    fn program_has_duration(program: Program) {
        let duration = program.duration();

        assert!(duration > Duration::zero());
    }
}
<commit_msg>Add Channel and Program impl<commit_after>use chrono::{serde::ts_nanoseconds, DateTime, Duration, Utc};
use serde::{Deserialize, Serialize};

/// Structure that contains information for a scheduled program
#[derive(Debug, Serialize, Deserialize)]
pub struct Program {
    /// Unique id for the program
    id: String,
    /// The title of the program
    title: String,
    /// List of categories that applies to the program
    categories: Vec<String>,
    /// Indicates whether this is available as a VOD
    #[serde(rename = "availableAsVod")]
    available_as_vod: bool,
    /// Indicates whether this is a rerun
    rerun: bool,
    /// Indicates whether this is a premiering episode
    premiere: bool,
    /// Indicates whether this is a live program
    live: bool,
    /// The time the program starts, as UTC time.
    #[serde(rename = "start", with = "ts_nanoseconds")]
    starts_at: DateTime<Utc>,
    /// The time the program ends, as UTC time.
    #[serde(rename = "stop", with = "ts_nanoseconds")]
    ends_at: DateTime<Utc>,
}

impl Program {
    /// Returns the unique ID of the program
    pub fn id(&self) -> &str {
        &self.id
    }

    /// Returns the title of the program
    pub fn title(&self) -> &str {
        &self.title
    }

    /// Returns the list of categories that applies to the program
    pub fn categories(&self) -> &Vec<String> {
        &self.categories
    }

    /// Returns whether this program is available as VOD
    pub fn available_as_vod(&self) -> bool {
        self.available_as_vod
    }

    /// Returns whether this program is a rerun
    pub fn rerun(&self) -> bool {
        self.rerun
    }

    /// Returns whether this program is premiering episode
    pub fn premiere(&self) -> bool {
        self.premiere
    }

    /// Returns whether this is a live program
    pub fn live(&self) -> bool {
        self.live
    }

    /// Returns the duration of the program
    pub fn duration(&self) -> Duration {
        self.ends_at - self.starts_at
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Channel {
    /// The unique ID of the channel
    id: String,
    /// The name of the channel
    title: String,
    /// An url to an icon for the channel
    icon: String,
    /// An url to a logo for the channel
    logo: String,
    /// An url to a logo for the channel in SVG format
    #[serde(rename = "svgLogo")]
    svg_logo: String,
    /// Sorting index
    sort: u32,
}

impl Channel {
    /// Returns the unique ID of the channel
    pub fn id(&self) -> &str {
        &self.id
    }

    /// Returns the name of the channel
    pub fn title(&self) -> &str {
        &self.title
    }

    /// Returns the url for the logo of the channel
    pub fn logo(&self) -> &str {
        &self.logo
    }

    /// Returns the url for the SVG logo of the channel
    pub fn svg_logo(&self) -> &str {
        &self.svg_logo
    }

    /// Returns the url for the icon of the channel
    pub fn icon(&self) -> &str {
        &self.icon
    }

    /// Returns the sorting index
    pub fn sort(&self) -> u32 {
        self.sort
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use rstest::*;

    #[fixture]
    fn program() -> Program {
        let json = r#"
            {
              "stop": 1585458000,
              "start": 1585454700,
              "categories": [
                "Kultur og Natur",
                "Programmer"
              ],
              "id": "20605495",
              "title": "Fantastiske floder: Mississippifloden",
              "availableAsVod": false,
              "rerun": true,
              "premiere": false,
              "live": false
            }
        "#;

        serde_json::from_str(&json).unwrap()
    }

    #[fixture]
    fn channel() -> Channel {
        let json = r#"
            {
              "id": "1",
              "title": "DR1",
              "icon": "https://epg-images.tv2.dk/channellogos/icon/1.png",
              "logo": "https://epg-images.tv2.dk/channellogos/logo/1.png",
              "svgLogo": "https://epg-images.tv2.dk/channellogos/svg/1.svg",
              "sort": 1
            }
        "#;

        serde_json::from_str(&json).unwrap()
    }

    #[rstest]
    fn it_deserializes_program(program: Program) {
        assert_eq!(program.title(), "Fantastiske floder: Mississippifloden");
        assert_eq!(program.id(), "20605495");
        assert_eq!(program.available_as_vod(), false);
        assert!(program.rerun());
        assert_eq!(program.premiere(), false);
        assert_eq!(program.live(), false);
        assert!(program.categories().len() > 0);
    }

    #[rstest]
    fn it_deserializes_channel(channel: Channel) {
        assert_eq!(channel.id(), "1");
        assert_eq!(channel.title(), "DR1");
        assert!(!channel.icon().is_empty());
        assert!(!channel.logo().is_empty());
        assert!(!channel.svg_logo().is_empty());
    }

    #[rstest]
    fn program_has_duration(program: Program) {
        let duration = program.duration();

        assert!(duration > Duration::zero());
    }
}
<|endoftext|>


<commit_before>extern crate xml;

use xml::{Element, Xml};

fn elem_with_text(tag_name: &'static str, chars: &str) -> Element {
    let mut elem = Element::new(tag_name, None, &[]);
    elem.text(chars);
    elem
}

trait ToXml<> {
    fn to_xml(&self) -> Element;
}

/// RSS version 2.0
pub struct Rss(pub Vec<Channel>);

impl ToXml for Rss {
    fn to_xml(&self) -> Element {
        let mut rss = Element::new("rss", None, &[("version", None, "2.0")]);

        let &Rss(ref channels) = self;
        for channel in channels {
            rss.tag(channel.to_xml());
        }

        rss
    }
}

impl Rss {
    fn to_string(&self) -> String {
        let mut ret = format!("{}", Xml::PINode("xml version='1.0' encoding='UTF-8'".to_string()));
        ret.push_str(&format!("{}", self.to_xml()));
        ret
    }
}

pub struct Channel {
    pub title: String,
    pub link: String,
    pub description: String,
    pub items: Vec<Item>,
}

impl ToXml for Channel {
    fn to_xml(&self) -> Element {
        let mut channel = Element::new("channel", None, &[]);

        channel.tag(elem_with_text("title", &self.title));
        channel.tag(elem_with_text("link", &self.link));
        channel.tag(elem_with_text("description", &self.description));

        for item in &self.items {
            channel.tag(item.to_xml());
        }

        channel
    }
}

pub struct Item {
    pub title: Option<String>,
    pub link: Option<String>,
    pub description: Option<String>,
}

impl ToXml for Item {
    fn to_xml(&self) -> Element {
        let mut item = Element::new("item", None, &[]);

        if let Some(ref s) = self.title {
            item.tag(elem_with_text("title", s));
        }

        if let Some(ref s) = self.link {
            item.tag(elem_with_text("link", s));
        }

        if let Some(ref s) = self.description {
            item.tag(elem_with_text("description", s));
        }

        item
    }
}

#[test]
fn test_consruct() {
    #![feature(collections)]

    let item = Item {
        title: Some(String::from_str("My first post!")),
        link: Some(String::from_str("http://myblog.com/post1")),
        description: Some(String::from_str("This is my first post")),
    };

    let channel = Channel {
        title: String::from_str("My Blog"),
        link: String::from_str("http://myblog.com"),
        description: String::from_str("Where I write stuff"),
        items: vec![item],
    };

    let rss = Rss(vec![channel]);
    assert_eq!(rss.to_string(), "<?xml version=\'1.0\' encoding=\'UTF-8\'?><rss version=\'2.0\'><channel><title>My Blog</title><link>http://myblog.com</link><description>Where I write stuff</description><item><title>My first post!</title><link>http://myblog.com/post1</link><description>This is my first post</description></item></channel></rss>");
}
<commit_msg>Rename trait to avoid conflicts<commit_after>extern crate xml;

use xml::{Element, Xml};

fn elem_with_text(tag_name: &'static str, chars: &str) -> Element {
    let mut elem = Element::new(tag_name, None, &[]);
    elem.text(chars);
    elem
}

trait ViaXml<> {
    fn to_xml(&self) -> Element;
}

/// RSS version 2.0
pub struct Rss(pub Vec<Channel>);

impl ViaXml for Rss {
    fn to_xml(&self) -> Element {
        let mut rss = Element::new("rss", None, &[("version", None, "2.0")]);

        let &Rss(ref channels) = self;
        for channel in channels {
            rss.tag(channel.to_xml());
        }

        rss
    }
}

impl Rss {
    fn to_string(&self) -> String {
        let mut ret = format!("{}", Xml::PINode("xml version='1.0' encoding='UTF-8'".to_string()));
        ret.push_str(&format!("{}", self.to_xml()));
        ret
    }
}

pub struct Channel {
    pub title: String,
    pub link: String,
    pub description: String,
    pub items: Vec<Item>,
}

impl ViaXml for Channel {
    fn to_xml(&self) -> Element {
        let mut channel = Element::new("channel", None, &[]);

        channel.tag(elem_with_text("title", &self.title));
        channel.tag(elem_with_text("link", &self.link));
        channel.tag(elem_with_text("description", &self.description));

        for item in &self.items {
            channel.tag(item.to_xml());
        }

        channel
    }
}

pub struct Item {
    pub title: Option<String>,
    pub link: Option<String>,
    pub description: Option<String>,
}

impl ViaXml for Item {
    fn to_xml(&self) -> Element {
        let mut item = Element::new("item", None, &[]);

        if let Some(ref s) = self.title {
            item.tag(elem_with_text("title", s));
        }

        if let Some(ref s) = self.link {
            item.tag(elem_with_text("link", s));
        }

        if let Some(ref s) = self.description {
            item.tag(elem_with_text("description", s));
        }

        item
    }
}

#[test]
fn test_consruct() {
    #![feature(collections)]

    let item = Item {
        title: Some(String::from_str("My first post!")),
        link: Some(String::from_str("http://myblog.com/post1")),
        description: Some(String::from_str("This is my first post")),
    };

    let channel = Channel {
        title: String::from_str("My Blog"),
        link: String::from_str("http://myblog.com"),
        description: String::from_str("Where I write stuff"),
        items: vec![item],
    };

    let rss = Rss(vec![channel]);
    assert_eq!(rss.to_string(), "<?xml version=\'1.0\' encoding=\'UTF-8\'?><rss version=\'2.0\'><channel><title>My Blog</title><link>http://myblog.com</link><description>Where I write stuff</description><item><title>My first post!</title><link>http://myblog.com/post1</link><description>This is my first post</description></item></channel></rss>");
}
<|endoftext|>


<commit_before>// TODO(nicholasbishop): remove this
#![allow(dead_code)]

mod key;
mod rangeset;

use key::Key;
use rangeset::{Range, RangeSet};
use std::collections::HashMap;

pub type VKey = Key;
pub type EKey = Key;
pub type FKey = Key;
pub type LKey = Key;
pub type FaceLen = u32;

pub struct Mesh {
    verts: HashMap<VKey, Vert>,
    edges: HashMap<EKey, Edge>,
    loops: HashMap<LKey, Loop>,
    faces: HashMap<FKey, Face>,

    vert_range_set: RangeSet,
    edge_range_set: RangeSet
}

impl Mesh {
    pub fn new() -> Mesh {
        Mesh {
            verts: HashMap::new(),
            edges: HashMap::new(),
            loops: HashMap::new(),
            faces: HashMap::new(),

            // TODO
            vert_range_set: RangeSet::new(Range::new(0, 0xffffffff - 1)),
            edge_range_set: RangeSet::new(Range::new(0, 0xffffffff - 1))
        }
    }

    pub fn add_vert(&mut self) -> Option<VKey> {
        if let Some(val) = self.vert_range_set.take_any_one() {
            let vkey = VKey::new(val);
            self.verts.insert(vkey, Vert { edges: Vec::new() });
            Some(vkey)
        } else {
            None
        }
    }

    pub fn add_edge(&mut self, v0: VKey, v1: VKey) -> Option<EKey> {
        // TODO(nicholasbishop): check that the verts are in the mesh,
        // are not the same vert, and that the edge doesn't exist yet.
        if let Some(val) = self.edge_range_set.take_any_one() {
            let ekey = EKey::new(val);
            self.verts.get_mut(&v0).unwrap().edges.push(ekey);
            self.verts.get_mut(&v1).unwrap().edges.push(ekey);
            self.edges.insert(ekey, Edge { verts: [v0, v1] });
            Some(ekey)
        } else {
            None
        }
    }
}

pub struct Vert {
    edges: Vec<EKey>
}

pub struct Edge {
    verts: [VKey; 2],
    // faces: Vec<FKey>
}

pub struct Loop {
    next: LKey,
    vert: VKey,
    edge: EKey,
    face: FKey
}

pub struct Face {
    len: FaceLen,
    first_loop: LKey
}

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

    #[test]
    fn test_add_vert() {
        let mut mesh = Mesh::new();
        assert!(mesh.add_vert().is_some());
        assert!(!mesh.verts.is_empty());
    }

    #[test]
    fn test_add_edge() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert().unwrap();
        let b = mesh.add_vert().unwrap();
        let e = mesh.add_edge(a, b).unwrap();
        assert!(mesh.verts[&a].edges.contains(&e));
        assert!(mesh.verts[&b].edges.contains(&e));
    }
}
<commit_msg>Checkpoint<commit_after>// TODO(nicholasbishop): remove this
#![allow(dead_code)]

mod key;
mod rangeset;

use key::Key;
use rangeset::{Range, RangeSet};
use std::collections::HashMap;

pub type VKey = Key;
pub type EKey = Key;
pub type FKey = Key;
pub type LKey = Key;
pub type FaceLen = u32;

pub struct Mesh {
    verts: HashMap<VKey, Vert>,
    edges: HashMap<EKey, Edge>,
    loops: HashMap<LKey, Loop>,
    faces: HashMap<FKey, Face>,

    vert_range_set: RangeSet,
    edge_range_set: RangeSet
}

impl Mesh {
    pub fn new() -> Mesh {
        Mesh {
            verts: HashMap::new(),
            edges: HashMap::new(),
            loops: HashMap::new(),
            faces: HashMap::new(),

            // TODO
            vert_range_set: RangeSet::new(Range::new(0, 0xffffffff - 1)),
            edge_range_set: RangeSet::new(Range::new(0, 0xffffffff - 1))
        }
    }

    /// Add a new isolated vertex and return its key. Fail and return
    /// None if there are no more vertex keys available.
    pub fn add_vert(&mut self) -> Option<VKey> {
        if let Some(val) = self.vert_range_set.take_any_one() {
            let vkey = VKey::new(val);
            self.verts.insert(vkey, Vert { edges: Vec::new() });
            Some(vkey)
        } else {
            None
        }
    }

    pub fn add_edge(&mut self, v0: VKey, v1: VKey) -> Option<EKey> {
        // TODO(nicholasbishop): check that the verts are in the mesh,
        // are not the same vert, and that the edge doesn't exist yet.
        if v0 == v1 {
            None
        } else {
            if let Some(val) = self.edge_range_set.take_any_one() {
                let ekey = EKey::new(val);
                self.verts.get_mut(&v0).unwrap().edges.push(ekey);
                self.verts.get_mut(&v1).unwrap().edges.push(ekey);
                self.edges.insert(ekey, Edge { verts: [v0, v1] });
                Some(ekey)
            } else {
                None
            }
        }
    }
}

pub struct Vert {
    edges: Vec<EKey>
}

pub struct Edge {
    verts: [VKey; 2],
    // faces: Vec<FKey>
}

pub struct Loop {
    next: LKey,
    vert: VKey,
    edge: EKey,
    face: FKey
}

pub struct Face {
    len: FaceLen,
    first_loop: LKey
}

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

    #[test]
    fn test_add_vert() {
        let mut mesh = Mesh::new();
        assert!(mesh.add_vert().is_some());
        assert!(!mesh.verts.is_empty());
    }

    #[test]
    fn test_add_edge() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert().unwrap();
        let b = mesh.add_vert().unwrap();

        // Add a valid edge
        let e = mesh.add_edge(a, b).unwrap();
        assert!(mesh.verts[&a].edges.contains(&e));
        assert!(mesh.verts[&b].edges.contains(&e));

        // Edge from a vertex to the same vertex
        assert!(mesh.add_edge(a, a).is_none());

        // Duplicate edge
        assert_eq!(mesh.add_edge(a, b).unwrap(), e);
        assert_eq!(mesh.add_edge(b, a).unwrap(), e);
    }
}
<|endoftext|>


<commit_before>// Code style
#![forbid(private_in_public)]
#![deny(unused_assignments)]

// Code style (development time)
#![allow(unused_macros)]
#![allow(dead_code)]

// Code style (temp)
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(unused_parens)]
#![allow(unused_mut)]
#![allow(unused_unsafe)]
#![allow(unreachable_code)]

// Safety
#![deny(overflowing_literals)]
#![deny(safe_packed_borrows)]

#![no_std]

#![feature(lang_items)]
#![feature(core_intrinsics)]
#![feature(panic_info_message)]
#![feature(asm)]
#![feature(ptr_internals)]
#![feature(const_fn)]
#![feature(const_vec_new)]
#![feature(naked_functions)]
#![feature(box_syntax, box_patterns)]
#![feature(box_into_raw_non_null)]
#![feature(stmt_expr_attributes)]
#![feature(alloc)]
#![feature(allocator_api)]

use core::alloc::Layout;
use core::panic::PanicInfo;

extern crate volatile;
extern crate rlibc;
extern crate spin;
extern crate x86_64;
extern crate cpuio;
#[macro_use]
extern crate bitflags;
extern crate bit_field;
#[macro_use]
extern crate static_assertions;

extern crate d7alloc;
extern crate d7staticfs;
extern crate d7ramfs;

#[macro_use]
extern crate alloc;

// Hardware:
#[macro_use]
mod vga_buffer;
#[macro_use]
mod util;
mod mem_map;
mod paging;
mod acpi;
mod pic;
// mod apic;
mod cpuid;
mod interrupt;
mod keyboard;
mod pit;
mod memory;
mod pci;
mod virtio;
mod disk_io;
mod staticfs;
// mod ide;
// mod nic;

// Software:
mod elf_parser;
mod time;
mod multitasking;
mod syscall;
mod filesystem;
mod kernel_shell;

/// The kernel main function
#[no_mangle]
pub extern fn rust_main() {
    rreset!();
    rprintln!("Loading the system...\n");

    // Finish system setup

    // Interrupt controller
    pic::init();
    // apic::init();

    // Memory allocation
    memory::init();

    // Interrupt system
    interrupt::init();

    // PIT
    pit::init();

    // CPU data
    cpuid::init();

    // Filesystem
    // filesystem::init();

    // Keyboard
    // keyboard::init();

    // PCI
    pci::init();

    // Disk IO (ATA, IDE, VirtIO)
    disk_io::init();

    // NIC
    // nic::init();

    // rreset!();
    rprintln!("Kernel initialized.\n");

    // Load modules
    if let Some(bytes) = staticfs::read_file("README.md") {
        let mut lines = 3;
        for b in bytes {
            if b == 0x0a {
                lines -= 1;
                if lines == 0 {
                    break;
                }
            }
            if (0x20 <= b && b <= 0x7f)  || b == 0x0a {
                rprint!("{}", b as char);
            }
        }
    } else {
        rprintln!("File not found");
    }

    // use multitasking::PROCMAN;
    //
    // {
    //     let ref mut pm = PROCMAN.lock();
    //     rprintln!("Did not crash!");
    //     let pid = pm.spawn();
    //     rprintln!("PID: {}", pid);
    //     rprintln!("Did not crash!");
    // }

    kernel_shell::run();

    loop {
        use time::{SYSCLOCK, busy_sleep_until};
        busy_sleep_until(SYSCLOCK.lock().after_seconds(5));
        // rprintln!("Sleep done");

        let success: u64;
        let result: u64;
        unsafe {
            asm!("
                mov rax, 0x1
                mov rdi, 0x2
                mov rsi, 0x3
                int 0xd7
            " : "={rax}"(success), "={rdx}"(result) :: "eax", "rdx", "rdi", "rsi" : "intel");
        }
        // let _ = success;
        // let _ = result;
        rprintln!("{:?} {:?}", success, result);
    }
}

#[global_allocator]
static HEAP_ALLOCATOR: d7alloc::GlobAlloc = d7alloc::GlobAlloc::new(
    d7alloc::BumpAllocator::new(d7alloc::HEAP_START, d7alloc::HEAP_START + d7alloc::HEAP_SIZE)
);

#[lang = "oom"]
#[no_mangle]
extern fn rust_oom(_: Layout) -> ! {
    unsafe {
        asm!("cli"::::"intel","volatile");
        panic_indicator!(0x4f4D4f21); // !M as in "No memory"
        asm!("jmp panic"::::"intel","volatile");
   }
   loop {}
}

#[cfg(not(test))]
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn _Unwind_Resume() -> ! {loop {}}

#[cfg(not(test))]
#[lang = "eh_personality"]
extern "C" fn eh_personality() -> ! {loop {}}

#[cfg(not(test))]
#[panic_handler]
#[allow(unused_variables)]
#[no_mangle]
extern "C" fn panic(info: &PanicInfo) -> ! {
    unsafe {
        // asm!("jmp panic"::::"intel","volatile");

        asm!("cli"::::"intel","volatile");
        panic_indicator!(0x4f214f21); // !!

        if let Some(location) = info.location() {
            rprintln!("\nKernel Panic: file: '{}', line: {}", location.file(), location.line());
        } else {
            rprintln!("\nKernel Panic: Location unavailable");
        }
        if let Some(msg) = info.message() {
            rprintln!("  {:?}", msg);
        } else {
            rprintln!("  Info unavailable");
        }
        asm!("jmp panic"::::"intel","volatile");
    }
    loop {}
}
<commit_msg>Deny unused_must_use lint<commit_after>// Code style
#![forbid(private_in_public)]
#![deny(unused_assignments)]

// Code style (development time)
#![allow(unused_macros)]
#![allow(dead_code)]

// Code style (temp)
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(unused_parens)]
#![allow(unused_mut)]
#![allow(unused_unsafe)]
#![allow(unreachable_code)]

// Safety
#![deny(overflowing_literals)]
#![deny(safe_packed_borrows)]
#![deny(unused_must_use)]

#![no_std]

#![feature(lang_items)]
#![feature(core_intrinsics)]
#![feature(panic_info_message)]
#![feature(asm)]
#![feature(ptr_internals)]
#![feature(const_fn)]
#![feature(const_vec_new)]
#![feature(naked_functions)]
#![feature(box_syntax, box_patterns)]
#![feature(box_into_raw_non_null)]
#![feature(stmt_expr_attributes)]
#![feature(alloc)]
#![feature(allocator_api)]

use core::alloc::Layout;
use core::panic::PanicInfo;

extern crate volatile;
extern crate rlibc;
extern crate spin;
extern crate x86_64;
extern crate cpuio;
#[macro_use]
extern crate bitflags;
extern crate bit_field;
#[macro_use]
extern crate static_assertions;

extern crate d7alloc;
extern crate d7staticfs;
extern crate d7ramfs;

#[macro_use]
extern crate alloc;

// Hardware:
#[macro_use]
mod vga_buffer;
#[macro_use]
mod util;
mod mem_map;
mod paging;
mod acpi;
mod pic;
// mod apic;
mod cpuid;
mod interrupt;
mod keyboard;
mod pit;
mod memory;
mod pci;
mod virtio;
mod disk_io;
mod staticfs;
// mod ide;
// mod nic;

// Software:
mod elf_parser;
mod time;
mod multitasking;
mod syscall;
mod filesystem;
mod kernel_shell;

/// The kernel main function
#[no_mangle]
pub extern fn rust_main() {
    rreset!();
    rprintln!("Loading the system...\n");

    // Finish system setup

    // Interrupt controller
    pic::init();
    // apic::init();

    // Memory allocation
    memory::init();

    // Interrupt system
    interrupt::init();

    // PIT
    pit::init();

    // CPU data
    cpuid::init();

    // Filesystem
    // filesystem::init();

    // Keyboard
    // keyboard::init();

    // PCI
    pci::init();

    // Disk IO (ATA, IDE, VirtIO)
    disk_io::init();

    // NIC
    // nic::init();

    // rreset!();
    rprintln!("Kernel initialized.\n");

    // Load modules
    if let Some(bytes) = staticfs::read_file("README.md") {
        let mut lines = 3;
        for b in bytes {
            if b == 0x0a {
                lines -= 1;
                if lines == 0 {
                    break;
                }
            }
            if (0x20 <= b && b <= 0x7f)  || b == 0x0a {
                rprint!("{}", b as char);
            }
        }
    } else {
        rprintln!("File not found");
    }

    // use multitasking::PROCMAN;
    //
    // {
    //     let ref mut pm = PROCMAN.lock();
    //     rprintln!("Did not crash!");
    //     let pid = pm.spawn();
    //     rprintln!("PID: {}", pid);
    //     rprintln!("Did not crash!");
    // }

    kernel_shell::run();

    loop {
        use time::{SYSCLOCK, busy_sleep_until};
        busy_sleep_until(SYSCLOCK.lock().after_seconds(5));
        // rprintln!("Sleep done");

        let success: u64;
        let result: u64;
        unsafe {
            asm!("
                mov rax, 0x1
                mov rdi, 0x2
                mov rsi, 0x3
                int 0xd7
            " : "={rax}"(success), "={rdx}"(result) :: "eax", "rdx", "rdi", "rsi" : "intel");
        }
        // let _ = success;
        // let _ = result;
        rprintln!("{:?} {:?}", success, result);
    }
}

#[global_allocator]
static HEAP_ALLOCATOR: d7alloc::GlobAlloc = d7alloc::GlobAlloc::new(
    d7alloc::BumpAllocator::new(d7alloc::HEAP_START, d7alloc::HEAP_START + d7alloc::HEAP_SIZE)
);

#[lang = "oom"]
#[no_mangle]
extern fn rust_oom(_: Layout) -> ! {
    unsafe {
        asm!("cli"::::"intel","volatile");
        panic_indicator!(0x4f4D4f21); // !M as in "No memory"
        asm!("jmp panic"::::"intel","volatile");
   }
   loop {}
}

#[cfg(not(test))]
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn _Unwind_Resume() -> ! {loop {}}

#[cfg(not(test))]
#[lang = "eh_personality"]
extern "C" fn eh_personality() -> ! {loop {}}

#[cfg(not(test))]
#[panic_handler]
#[allow(unused_variables)]
#[no_mangle]
extern "C" fn panic(info: &PanicInfo) -> ! {
    unsafe {
        // asm!("jmp panic"::::"intel","volatile");

        asm!("cli"::::"intel","volatile");
        panic_indicator!(0x4f214f21); // !!

        if let Some(location) = info.location() {
            rprintln!("\nKernel Panic: file: '{}', line: {}", location.file(), location.line());
        } else {
            rprintln!("\nKernel Panic: Location unavailable");
        }
        if let Some(msg) = info.message() {
            rprintln!("  {:?}", msg);
        } else {
            rprintln!("  Info unavailable");
        }
        asm!("jmp panic"::::"intel","volatile");
    }
    loop {}
}
<|endoftext|>


<commit_before>//! Differentiable operations and tensors backed by [ndarray](https://github.com/rust-ndarray/ndarray).
//!
//! ## Motivation
//! Machine learning is one of the field where Rust lagging behind other languages.
//! The aim of this crate is to show that Rust has the capability to imprement efficient and full-featured dataflow graph naturally.
//! Moreover, the core of this crate is quite small compared to others (due to being implemented in pure Rust and ndarray),
//! therefore it might be reasonable for those who are not familiar with how this kind of library works.
//!
//! ## Features
//! ### Lazy, lightweight tensor evaluation
//! Computation graphs are created on the fly (a.k.a. *define-by-run*), but are not evaluated until `eval` is called.
//! This mechanism balances better performance and flexibility.
//!
//! ```rust
//! use autograd as ag;
//!
//! ag::with(|g: &mut ag::Graph<_>| {
//!     let a: ag::Tensor<f32> = g.ones(&[60]);
//!     let b: ag::Tensor<f32> = g.ones(&[24]);
//!     let c: ag::Tensor<f32> = g.reshape(a, &[3, 4, 5]);
//!     let d: ag::Tensor<f32> = g.reshape(b, &[4, 3, 2]);
//!     let e: ag::Tensor<f32> = g.tensordot(c, d, &[1, 0], &[0, 1]);
//!     let result: ag::ndarray::Array<_, _> = e.eval(&[]).unwrap();  // Getting `ndarray::Array` here.
//! });
//! ```
//!
//! ### Reverse-mode automatic differentiation
//! There are a lot of [built-in operations](https://docs.rs/autograd/1.0.0/autograd/struct.Graph.html)
//! that support *higher-order* derivatives, and
//! you can also [define your own differentiable ops](https://docs.rs/autograd/1.0.0/autograd/op/trait.Op.html) with ndarrays easily.
//!
//! Here we are just computing partial derivatives of `z = 2x^2 + 3y + 1`.
//!
//! ```rust
//! use autograd as ag;
//!
//! # fn main() {
//! ag::with(|g: &mut ag::Graph<_>| {
//!     let x = g.placeholder(&[]);
//!     let y = g.placeholder(&[]);
//!     let z = 2.*x*x + 3.*y + 1.;
//!
//!     // dz/dy
//!     let gy = &g.grad(&[z], &[y])[0];
//!     println!("{:?}", gy.eval(&[]));   // => Ok(3.)
//!
//!     // dz/dx (requires to fill the placeholder `x`)
//!     let gx = &g.grad(&[z], &[x])[0];
//!     let feed = ag::ndarray::arr0(2.);
//!     println!("{:?}", gx.eval(&[x.given(feed.view())]));  // => Ok(8.)
//!     // ddz/dx (differentiates `z` again)
//!     let ggx = &g.grad(&[gx], &[x])[0];
//!     println!("{:?}", ggx.eval(&[]));  // => Ok(4.)
//! });
//! # }
//! ```
//!
//! ### Neural networks
//! This crate has various low-level features inspired by tensorflow/theano to train neural networks.
//! Since computation graphs require only bare minimum of heap allocations, the overhead is small, even for complex networks.
//! ```rust
//! // This is a softmax regression for MNIST digits classification with Adam.
//! // This achieves 0.918 test accuracy after 3 epochs (0.11 sec/epoch on 2.7GHz Intel Core i5).
//! use autograd::{self as ag, Graph, optimizers::adam, ndarray_ext as arr, tensor::Variable};
//!
//! let rng = ag::ndarray_ext::ArrayRng::<f32>::default();
//! let w_arr = arr::into_shared(rng.glorot_uniform(&[28 * 28, 10]));
//! let b_arr = arr::into_shared(arr::zeros(&[1, 10]));
//! let adam_state = adam::AdamState::new(&[&w_arr, &b_arr]);
//!
//! let max_epoch = 3;
//!
//! for epoch in 0..max_epoch {
//!     ag::with(|g| {
//!         let w = g.variable(w_arr.clone());
//!         let b = g.variable(b_arr.clone());
//!         let x = g.placeholder(&[-1, 28*28]);
//!         let y = g.placeholder(&[-1]);
//!         let z = g.matmul(x, w) + b;
//!         let mean_loss = g.reduce_mean(g.sparse_softmax_cross_entropy(z, &y), &[0], false);
//!         let grads = &g.grad(&[&mean_loss], &[w, b]);
//!         let update_ops: &[ag::Tensor<f32>] =
//!             &adam::Adam::default().compute_updates(&[w, b], grads, &adam_state, g);
//!
//!         // let batch_size = 200isize;
//!         // let num_samples = x_train.shape()[0];
//!         // let num_batches = num_samples / batch_size as usize;
//!         // for i in get_permutation(num_batches) {
//!         //     let i = i as isize * batch_size;
//!         //     let x_batch = x_train.slice(s![i..i + batch_size, ..]).into_dyn();
//!         //     let y_batch = y_train.slice(s![i..i + batch_size, ..]).into_dyn();
//!         //     g.eval(update_ops, &[x.given(x_batch), y.given(y_batch)]);
//!         // }
//!     });
//! }
//! ```
//!
//! ### Hooks
//! You can register hooks on `ag::Tensor` objects for debugging.
//!
//! ```rust
//! use autograd as ag;
//!
//! ag::with(|g| {
//!     let a: ag::Tensor<f32> = g.zeros(&[4, 2]).show();
//!     let b: ag::Tensor<f32> = g.ones(&[2, 3]).show_shape();
//!     let c = g.matmul(a, b).show_with("MatMul:");
//!
//!     c.eval(&[]);
//!     // [[0.0, 0.0],
//!     // [0.0, 0.0],
//!     // [0.0, 0.0],
//!     // [0.0, 0.0]] shape=[4, 2], strides=[2, 1], layout=C (0x1)
//!     //
//!     // [2, 3]
//!     //
//!     // MatMul:
//!     //  [[0.0, 0.0, 0.0],
//!     //  [0.0, 0.0, 0.0],
//!     //  [0.0, 0.0, 0.0],
//!     //  [0.0, 0.0, 0.0]] shape=[4, 3], strides=[3, 1], layout=C (0x1), dynamic ndim=2
//! });
//! ```
//!

#[allow(unused_imports)]
// Expose to prevent version conflict
#[macro_use(s)]
/// re-exported for convenience and version-compatibility
pub extern crate ndarray;
#[cfg(feature = "mkl")]
extern crate intel_mkl_src;
extern crate libc;
#[cfg(not(feature = "mkl"))]
extern crate matrixmultiply;
extern crate num;
extern crate num_traits;
/// re-exported for convenience and version-compatibility
pub extern crate rand;
extern crate rand_distr;
extern crate rayon;
extern crate rustc_hash;
pub(crate) extern crate smallvec;

mod gradient;
pub(crate) mod graph;
mod hook;
pub mod ndarray_ext;
pub mod op;
mod ops;
pub mod optimizers;
mod runtime;
pub mod tensor;
pub mod test_helper;

use rustc_hash::FxHasher;
use std::any::TypeId;
use std::collections::{HashMap, HashSet};
use std::fmt;
use std::hash::BuildHasherDefault;

pub(crate) type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
pub(crate) type FxHashSet<K> = HashSet<K, BuildHasherDefault<FxHasher>>;

/// Primitive type in this crate, which is actually a decorated `num_traits::Float`.
pub trait Float:
    num_traits::Float
    + num_traits::NumAssignOps
    + Copy
    + Send
    + Sync
    + fmt::Display
    + fmt::Debug
    + Sized
    + 'static
{
}

#[doc(hidden)]
/// Internal trait.
pub trait Int:
    num::Integer
    + num_traits::NumAssignOps
    + num_traits::ToPrimitive
    + Copy
    + Send
    + fmt::Display
    + Sized
    + 'static
{
}

impl<T> Float for T where
    T: num::Float
        + num_traits::NumAssignOps
        + Copy
        + Send
        + Sync
        + fmt::Display
        + fmt::Debug
        + Sized
        + 'static
{
}

impl<T> Int for T where
    T: num::Integer
        + num_traits::NumAssignOps
        + num_traits::ToPrimitive
        + Copy
        + Send
        + Sync
        + fmt::Display
        + Sized
        + 'static
{
}

#[inline(always)]
/// Return `true` if `A` and `B` are the same type
pub(crate) fn same_type<A: 'static, B: 'static>() -> bool {
    TypeId::of::<A>() == TypeId::of::<B>()
}

pub use crate::ndarray_ext::array_gen;

pub use crate::ndarray_ext::{NdArray, NdArrayView, NdArrayViewMut};

pub use crate::runtime::{Eval, Feed};

pub use crate::tensor::Tensor;

pub(crate) use crate::ndarray_ext::ArrRepr;

pub use crate::graph::{run, with, Graph};

/// Error during tensor's evaluation.
#[derive(Debug, PartialEq)]
pub enum EvalError {
    /// Error during `Op`'s computation.
    OpError(op::OpError),
    /// A value of tensor is empty.
    ///
    /// For example, compute results of inplace ops (e.g. optimizers) are not available
    /// and are represented as `Empty`.
    Empty,
}

impl std::error::Error for EvalError {}

impl fmt::Display for EvalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            EvalError::OpError(e) => e.fmt(f),
            EvalError::Empty => write!(f, "Empty return value from a stateful op"),
        }
    }
}
<commit_msg>Fixed typo in documentation<commit_after>//! Differentiable operations and tensors backed by [ndarray](https://github.com/rust-ndarray/ndarray).
//!
//! ## Motivation
//! Machine learning is one of the field where Rust lagging behind other languages.
//! The aim of this crate is to show that Rust has the capability to implement efficient and full-featured dataflow graph naturally.
//! Moreover, the core of this crate is quite small compared to others (due to being implemented in pure Rust and ndarray),
//! therefore it might be reasonable for those who are not familiar with how this kind of library works.
//!
//! ## Features
//! ### Lazy, lightweight tensor evaluation
//! Computation graphs are created on the fly (a.k.a. *define-by-run*), but are not evaluated until `eval` is called.
//! This mechanism balances better performance and flexibility.
//!
//! ```rust
//! use autograd as ag;
//!
//! ag::with(|g: &mut ag::Graph<_>| {
//!     let a: ag::Tensor<f32> = g.ones(&[60]);
//!     let b: ag::Tensor<f32> = g.ones(&[24]);
//!     let c: ag::Tensor<f32> = g.reshape(a, &[3, 4, 5]);
//!     let d: ag::Tensor<f32> = g.reshape(b, &[4, 3, 2]);
//!     let e: ag::Tensor<f32> = g.tensordot(c, d, &[1, 0], &[0, 1]);
//!     let result: ag::ndarray::Array<_, _> = e.eval(&[]).unwrap();  // Getting `ndarray::Array` here.
//! });
//! ```
//!
//! ### Reverse-mode automatic differentiation
//! There are a lot of [built-in operations](https://docs.rs/autograd/1.0.0/autograd/struct.Graph.html)
//! that support *higher-order* derivatives, and
//! you can also [define your own differentiable ops](https://docs.rs/autograd/1.0.0/autograd/op/trait.Op.html) with ndarrays easily.
//!
//! Here we are just computing partial derivatives of `z = 2x^2 + 3y + 1`.
//!
//! ```rust
//! use autograd as ag;
//!
//! # fn main() {
//! ag::with(|g: &mut ag::Graph<_>| {
//!     let x = g.placeholder(&[]);
//!     let y = g.placeholder(&[]);
//!     let z = 2.*x*x + 3.*y + 1.;
//!
//!     // dz/dy
//!     let gy = &g.grad(&[z], &[y])[0];
//!     println!("{:?}", gy.eval(&[]));   // => Ok(3.)
//!
//!     // dz/dx (requires to fill the placeholder `x`)
//!     let gx = &g.grad(&[z], &[x])[0];
//!     let feed = ag::ndarray::arr0(2.);
//!     println!("{:?}", gx.eval(&[x.given(feed.view())]));  // => Ok(8.)
//!     // ddz/dx (differentiates `z` again)
//!     let ggx = &g.grad(&[gx], &[x])[0];
//!     println!("{:?}", ggx.eval(&[]));  // => Ok(4.)
//! });
//! # }
//! ```
//!
//! ### Neural networks
//! This crate has various low-level features inspired by tensorflow/theano to train neural networks.
//! Since computation graphs require only bare minimum of heap allocations, the overhead is small, even for complex networks.
//! ```rust
//! // This is a softmax regression for MNIST digits classification with Adam.
//! // This achieves 0.918 test accuracy after 3 epochs (0.11 sec/epoch on 2.7GHz Intel Core i5).
//! use autograd::{self as ag, Graph, optimizers::adam, ndarray_ext as arr, tensor::Variable};
//!
//! let rng = ag::ndarray_ext::ArrayRng::<f32>::default();
//! let w_arr = arr::into_shared(rng.glorot_uniform(&[28 * 28, 10]));
//! let b_arr = arr::into_shared(arr::zeros(&[1, 10]));
//! let adam_state = adam::AdamState::new(&[&w_arr, &b_arr]);
//!
//! let max_epoch = 3;
//!
//! for epoch in 0..max_epoch {
//!     ag::with(|g| {
//!         let w = g.variable(w_arr.clone());
//!         let b = g.variable(b_arr.clone());
//!         let x = g.placeholder(&[-1, 28*28]);
//!         let y = g.placeholder(&[-1]);
//!         let z = g.matmul(x, w) + b;
//!         let mean_loss = g.reduce_mean(g.sparse_softmax_cross_entropy(z, &y), &[0], false);
//!         let grads = &g.grad(&[&mean_loss], &[w, b]);
//!         let update_ops: &[ag::Tensor<f32>] =
//!             &adam::Adam::default().compute_updates(&[w, b], grads, &adam_state, g);
//!
//!         // let batch_size = 200isize;
//!         // let num_samples = x_train.shape()[0];
//!         // let num_batches = num_samples / batch_size as usize;
//!         // for i in get_permutation(num_batches) {
//!         //     let i = i as isize * batch_size;
//!         //     let x_batch = x_train.slice(s![i..i + batch_size, ..]).into_dyn();
//!         //     let y_batch = y_train.slice(s![i..i + batch_size, ..]).into_dyn();
//!         //     g.eval(update_ops, &[x.given(x_batch), y.given(y_batch)]);
//!         // }
//!     });
//! }
//! ```
//!
//! ### Hooks
//! You can register hooks on `ag::Tensor` objects for debugging.
//!
//! ```rust
//! use autograd as ag;
//!
//! ag::with(|g| {
//!     let a: ag::Tensor<f32> = g.zeros(&[4, 2]).show();
//!     let b: ag::Tensor<f32> = g.ones(&[2, 3]).show_shape();
//!     let c = g.matmul(a, b).show_with("MatMul:");
//!
//!     c.eval(&[]);
//!     // [[0.0, 0.0],
//!     // [0.0, 0.0],
//!     // [0.0, 0.0],
//!     // [0.0, 0.0]] shape=[4, 2], strides=[2, 1], layout=C (0x1)
//!     //
//!     // [2, 3]
//!     //
//!     // MatMul:
//!     //  [[0.0, 0.0, 0.0],
//!     //  [0.0, 0.0, 0.0],
//!     //  [0.0, 0.0, 0.0],
//!     //  [0.0, 0.0, 0.0]] shape=[4, 3], strides=[3, 1], layout=C (0x1), dynamic ndim=2
//! });
//! ```
//!

#[allow(unused_imports)]
// Expose to prevent version conflict
#[macro_use(s)]
/// re-exported for convenience and version-compatibility
pub extern crate ndarray;
#[cfg(feature = "mkl")]
extern crate intel_mkl_src;
extern crate libc;
#[cfg(not(feature = "mkl"))]
extern crate matrixmultiply;
extern crate num;
extern crate num_traits;
/// re-exported for convenience and version-compatibility
pub extern crate rand;
extern crate rand_distr;
extern crate rayon;
extern crate rustc_hash;
pub(crate) extern crate smallvec;

mod gradient;
pub(crate) mod graph;
mod hook;
pub mod ndarray_ext;
pub mod op;
mod ops;
pub mod optimizers;
mod runtime;
pub mod tensor;
pub mod test_helper;

use rustc_hash::FxHasher;
use std::any::TypeId;
use std::collections::{HashMap, HashSet};
use std::fmt;
use std::hash::BuildHasherDefault;

pub(crate) type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
pub(crate) type FxHashSet<K> = HashSet<K, BuildHasherDefault<FxHasher>>;

/// Primitive type in this crate, which is actually a decorated `num_traits::Float`.
pub trait Float:
    num_traits::Float
    + num_traits::NumAssignOps
    + Copy
    + Send
    + Sync
    + fmt::Display
    + fmt::Debug
    + Sized
    + 'static
{
}

#[doc(hidden)]
/// Internal trait.
pub trait Int:
    num::Integer
    + num_traits::NumAssignOps
    + num_traits::ToPrimitive
    + Copy
    + Send
    + fmt::Display
    + Sized
    + 'static
{
}

impl<T> Float for T where
    T: num::Float
        + num_traits::NumAssignOps
        + Copy
        + Send
        + Sync
        + fmt::Display
        + fmt::Debug
        + Sized
        + 'static
{
}

impl<T> Int for T where
    T: num::Integer
        + num_traits::NumAssignOps
        + num_traits::ToPrimitive
        + Copy
        + Send
        + Sync
        + fmt::Display
        + Sized
        + 'static
{
}

#[inline(always)]
/// Return `true` if `A` and `B` are the same type
pub(crate) fn same_type<A: 'static, B: 'static>() -> bool {
    TypeId::of::<A>() == TypeId::of::<B>()
}

pub use crate::ndarray_ext::array_gen;

pub use crate::ndarray_ext::{NdArray, NdArrayView, NdArrayViewMut};

pub use crate::runtime::{Eval, Feed};

pub use crate::tensor::Tensor;

pub(crate) use crate::ndarray_ext::ArrRepr;

pub use crate::graph::{run, with, Graph};

/// Error during tensor's evaluation.
#[derive(Debug, PartialEq)]
pub enum EvalError {
    /// Error during `Op`'s computation.
    OpError(op::OpError),
    /// A value of tensor is empty.
    ///
    /// For example, compute results of inplace ops (e.g. optimizers) are not available
    /// and are represented as `Empty`.
    Empty,
}

impl std::error::Error for EvalError {}

impl fmt::Display for EvalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            EvalError::OpError(e) => e.fmt(f),
            EvalError::Empty => write!(f, "Empty return value from a stateful op"),
        }
    }
}
<|endoftext|>


<commit_before>/*
 * A basic EBML parser for Rust. Gives methods for both approaches; full parsing
 * of an EBML file in-memory or incremental sequential parsing of nodes for
 * environments that are more memory-constrained.
 *
 * The full parser allows you to get all sub-elements of a node in one call,
 * because each node has a reference to the data it contains. All of the data is
 * loaded into memory when the root node is parsed.
 *
 * The PartialElement only reads the data it needs to get the header of any
 * single element. So if the data source is a file the full parser will load the
 * whole file to memory, while the partial parser will only load at most one leaf
 * node's value plus its id and size.
 *
 * The partial parser stores the offset of each node in the input stream, which
 * is then used to jump to the node's data in the stream. This may cause the
 * partial parser to do more random seeking.
 */

extern crate time;
//use std::io::Memreader;
//use time::Timespec;
use std::io::IoResult;

pub mod rebml {
	// Element for an incremental reader
	struct ElementHeader {
		id: u32,
		size: u64
	}

	/*// Element for a full reader
	struct Element {
		header: ElementHeader,
		data: &[u8]
	}*/

	enum Value {
		SubElement(ElementHeader),
		Uint(u64),
		Int(i64),
		Str(String),
		Date(time::Timespec),
		Bin(&[u8]),
		Nil, // Empty element
	}

	enum Type {

	}

	/*fn full_parse(input: &Reader) -> IoResult<Element> {
		let mut ele: Element;
		// Attempt to read root element
		match (input.read_be_u64()) {
			Ok(val) => ele.header.id = val,
			Error(err) => return Error(err),
		}
	}*/

	fn partial_parse(input: &Reader) -> IoResult<ElementHeader> {
	}

	/*impl Element {
		fn sub_elements() -> IoResult<Vec<Element>> {
		}

		fn value() -> IoResult<Option<Value>> {

		}
		// TODO: get properties
	}*/

	impl ElementHeader {
		/*
		 * Get next the next node after this one in the given input stream.
		 */
		fn next(input: &Reader) -> IoResult<ElementHeader> {
		}

		/*
		 * Get the value of this node
		 */
		fn value(input: &Reader) -> IoResult<Value> {
		}
		// TODO: method to read sub/adjacent PartialElement
		// TODO: get properties
	}
}
<commit_msg>More bumming around with the API.<commit_after>/*
* A basic EBML parser for Rust. Gives methods for both approaches; full parsing
* of an EBML file in-memory or incremental sequential parsing of nodes for
* environments that are more memory-constrained.
*
* The full parser allows you to get all sub-elements of a node in one call,
* because each node has a reference to the data it contains. All of the data is
* loaded into memory when the root node is parsed.
*
* The PartialElement only reads the data it needs to get the header of any
* single element. So if the data source is a file the full parser will load the
* whole file to memory, while the partial parser will only load at most one leaf
* node's value plus its id and size.
*
* The partial parser stores the offset of each node in the input stream, which
* is then used to jump to the node's data in the stream. This may cause the
* partial parser to do more random seeking.
*/

//extern crate time;
//use std::io::Memreader;
//use time::Timespec;
use std::io;

mod rebml {
    mod incremental {
        pub struct Parser {
            input: &Reader,
            id: u32,
            size: u64
        }

        impl Parser {
            // Create new EBML Parser and read in the first tag, if any. Consumes the input stream.
            fn new(&self) -> IoResult<Parser> {

            }

            /*
            Get next the next node after this one in the given input stream.
            */
            fn next(&self) -> Option<IoError> {
            }

            /*
            Get the subnode below this one, if any exists (returns IoError on failure)
            */
            fn down(&self) -> Option<IoError> {
            }

            /*
            Get the current depth in the Element tree
            */
            fn level(&self) -> u32 {}

            /*
            Get the value of this node
            */
            fn value(input: &Reader) -> IoResult<Value> {
            }
        }
    }
}
<|endoftext|>


<commit_before>//! This crate contains various data structures useful for quickly performing interval
//! queries or modifications in some array.
//!
//! The data structures in this crate are all trees. The trees are represented using an
//! array for high performance and low memory usage.
//! Despite the name of the crate, not every tree in this crate is a segment tree.
//!
//! The [`SegmentPoint`] data structure allows interval queries and point updates to an
//! array in logaritmic time. It is well known for solving the [range minimum query][1]
//! problem. This is the data structure traditionally known as a segment tree.
//!
//! The [`PointSegment`] data structure allows point queries and interval updates to an
//! array in logaritmic time.
//!
//! The [`PrefixPoint`] data structure is a weaker version of the [`SegmentPoint`] data
//! structure, since the intervals must start at the index `0` and the operator must be
//! [commutative][2].  However it has the advantage that it uses half the memory and the
//! size of the array can be changed. This data structure is also known as a
//! [fenwick tree][3].
//!
//! The similar crate [`prefix-sum`] might also be of interest.
//!
//! This crate has the optional feature [`num-bigint`], which implements the operations in
//! [`ops`] for [`BigInt`] and [`BigUint`].
//!
//! [1]: https://en.wikipedia.org/wiki/Range_minimum_query
//! [2]: ops/trait.Commutative.html
//! [3]: https://en.wikipedia.org/wiki/Fenwick_tree
//! [`SegmentPoint`]: struct.SegmentPoint.html
//! [`PointSegment`]: struct.PointSegment.html
//! [`PrefixPoint`]: struct.PrefixPoint.html
//! [`num-bigint`]: https://crates.io/crates/num-bigint
//! [`BigInt`]: https://docs.rs/num-bigint/0.2/num_bigint/struct.BigInt.html
//! [`BigUint`]: https://docs.rs/num-bigint/0.2/num_bigint/struct.BigUint.html
//! [`prefix-sum`]: https://crates.io/crates/prefix-sum
//! [`ops`]: ops/index.html

pub mod ops;
pub mod maybe_owned;
pub use crate::fenwick::PrefixPoint;
pub use crate::propagating::PointSegment;
pub use crate::segment_tree::SegmentPoint;

mod fenwick;
mod propagating;
mod segment_tree;
<commit_msg>Add note about blog post<commit_after>//! This crate contains various data structures useful for quickly performing interval
//! queries or modifications in some array.
//!
//! The data structures in this crate are all trees. The trees are represented using an
//! array for high performance and low memory usage.
//! Despite the name of the crate, not every tree in this crate is a segment tree.
//!
//! The [`SegmentPoint`] data structure allows interval queries and point updates to an
//! array in logaritmic time. It is well known for solving the [range minimum query][1]
//! problem. This is the data structure traditionally known as a segment tree.
//!
//! The [`PointSegment`] data structure allows point queries and interval updates to an
//! array in logaritmic time.
//!
//! The [`PrefixPoint`] data structure is a weaker version of the [`SegmentPoint`] data
//! structure, since the intervals must start at the index `0` and the operator must be
//! [commutative][2].  However it has the advantage that it uses half the memory and the
//! size of the array can be changed. This data structure is also known as a
//! [fenwick tree][3].
//!
//! The segment tree in this crate is inspired by [this blog post][4].
//!
//! The similar crate [`prefix-sum`] might also be of interest.
//!
//! This crate has the optional feature [`num-bigint`], which implements the operations in
//! [`ops`] for [`BigInt`] and [`BigUint`].
//!
//! [1]: https://en.wikipedia.org/wiki/Range_minimum_query
//! [2]: ops/trait.Commutative.html
//! [3]: https://en.wikipedia.org/wiki/Fenwick_tree
//! [4]: https://codeforces.com/blog/entry/18051
//! [`SegmentPoint`]: struct.SegmentPoint.html
//! [`PointSegment`]: struct.PointSegment.html
//! [`PrefixPoint`]: struct.PrefixPoint.html
//! [`num-bigint`]: https://crates.io/crates/num-bigint
//! [`BigInt`]: https://docs.rs/num-bigint/0.2/num_bigint/struct.BigInt.html
//! [`BigUint`]: https://docs.rs/num-bigint/0.2/num_bigint/struct.BigUint.html
//! [`prefix-sum`]: https://crates.io/crates/prefix-sum
//! [`ops`]: ops/index.html

pub mod ops;
pub mod maybe_owned;
pub use crate::fenwick::PrefixPoint;
pub use crate::propagating::PointSegment;
pub use crate::segment_tree::SegmentPoint;

mod fenwick;
mod propagating;
mod segment_tree;
<|endoftext|>


<commit_before>//! Pure Rust implementation of Ryū, an algorithm to quickly convert floating
//! point numbers to decimal strings.
//!
//! The PLDI'18 paper [*Ryū: fast float-to-string conversion*][paper] by Ulf
//! Adams includes a complete correctness proof of the algorithm. The paper is
//! available under the creative commons CC-BY-SA license.
//!
//! This Rust implementation is a line-by-line port of Ulf Adams' implementation
//! in C, [https://github.com/ulfjack/ryu][upstream]. The [`ryu::raw`][raw]
//! module exposes exactly the API and formatting of the C implementation as
//! unsafe pure Rust functions. There is additionally a safe API as demonstrated
//! in the example code below. The safe API uses the same underlying Ryū
//! algorithm but diverges from the formatting of the C implementation to
//! produce more human-readable output, for example `0.3` rather than `3E-1`.
//!
//! [paper]: https://dl.acm.org/citation.cfm?id=3192369
//! [upstream]: https://github.com/ulfjack/ryu
//! [raw]: raw/index.html
//!
//! # Examples
//!
//! ```rust
//! extern crate ryu;
//!
//! fn main() {
//!     let mut buffer = ryu::Buffer::new();
//!     let printed = buffer.format(1.234);
//!     assert_eq!(printed, "1.234");
//! }
//! ```

#![no_std]
#![doc(html_root_url = "https://docs.rs/ryu/0.2.7")]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        cast_lossless,
        cyclomatic_complexity,
        many_single_char_names,
        needless_pass_by_value,
        unreadable_literal,
    )
)]

#[cfg(feature = "no-panic")]
extern crate no_panic;

mod buffer;
mod common;
mod d2s;
#[cfg(not(feature = "small"))]
mod d2s_full_table;
mod d2s_intrinsics;
#[cfg(feature = "small")]
mod d2s_small_table;
mod digit_table;
mod f2s;
mod pretty;

pub use buffer::{Buffer, Float};

/// Unsafe functions that exactly mirror the API of the C implementation of Ryū.
pub mod raw {
    pub use d2s::d2s_buffered_n;
    pub use f2s::f2s_buffered_n;
    pub use pretty::d2s_buffered_n as pretty_d2s_buffered_n;
    pub use pretty::f2s_buffered_n as pretty_f2s_buffered_n;
}
<commit_msg>Disable warning about tool attrs<commit_after>//! Pure Rust implementation of Ryū, an algorithm to quickly convert floating
//! point numbers to decimal strings.
//!
//! The PLDI'18 paper [*Ryū: fast float-to-string conversion*][paper] by Ulf
//! Adams includes a complete correctness proof of the algorithm. The paper is
//! available under the creative commons CC-BY-SA license.
//!
//! This Rust implementation is a line-by-line port of Ulf Adams' implementation
//! in C, [https://github.com/ulfjack/ryu][upstream]. The [`ryu::raw`][raw]
//! module exposes exactly the API and formatting of the C implementation as
//! unsafe pure Rust functions. There is additionally a safe API as demonstrated
//! in the example code below. The safe API uses the same underlying Ryū
//! algorithm but diverges from the formatting of the C implementation to
//! produce more human-readable output, for example `0.3` rather than `3E-1`.
//!
//! [paper]: https://dl.acm.org/citation.cfm?id=3192369
//! [upstream]: https://github.com/ulfjack/ryu
//! [raw]: raw/index.html
//!
//! # Examples
//!
//! ```rust
//! extern crate ryu;
//!
//! fn main() {
//!     let mut buffer = ryu::Buffer::new();
//!     let printed = buffer.format(1.234);
//!     assert_eq!(printed, "1.234");
//! }
//! ```

#![no_std]
#![doc(html_root_url = "https://docs.rs/ryu/0.2.7")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        cast_lossless,
        cyclomatic_complexity,
        many_single_char_names,
        needless_pass_by_value,
        unreadable_literal,
    )
)]

#[cfg(feature = "no-panic")]
extern crate no_panic;

mod buffer;
mod common;
mod d2s;
#[cfg(not(feature = "small"))]
mod d2s_full_table;
mod d2s_intrinsics;
#[cfg(feature = "small")]
mod d2s_small_table;
mod digit_table;
mod f2s;
mod pretty;

pub use buffer::{Buffer, Float};

/// Unsafe functions that exactly mirror the API of the C implementation of Ryū.
pub mod raw {
    pub use d2s::d2s_buffered_n;
    pub use f2s::f2s_buffered_n;
    pub use pretty::d2s_buffered_n as pretty_d2s_buffered_n;
    pub use pretty::f2s_buffered_n as pretty_f2s_buffered_n;
}
<|endoftext|>


<commit_before>pub trait Interpolate: Clone {
    #[inline]
    fn bilerp(v: [[Self; 2]; 2], x: f64, y: f64) -> Self {
        let v0 = Interpolate::lerp([v[0][0].clone(), v[0][1].clone()], y);
        let v1 = Interpolate::lerp([v[1][0].clone(), v[1][1].clone()], y);
        Interpolate::lerp([v0, v1], x)
    }

    #[inline]
    fn lerp(v: [Self; 2], x: f64) -> Self;
}

impl Interpolate for f64 {
    fn bilerp(v: [[f64; 2]; 2], x: f64, y: f64) -> f64 {
        v[0][0]*(1.0-x)*(1.0-y) + v[1][0]*x*(1.0-y) + v[0][1]*(1.0-x)*y + v[1][1]*x*y
    }

    fn lerp(v: [f64; 2], x: f64) -> f64 {
        v[0] + x * (v[1] - v[0])
    }
}

impl Interpolate for f32 {
    fn bilerp(v: [[f32; 2]; 2], x: f64, y: f64) -> f32 {
        let x = x as f32;
        let y = y as f32;
        (v[0][0]*(1.0-x)*(1.0-y) + v[1][0]*x*(1.0-y) + v[0][1]*(1.0-x)*y + v[1][1]*x*y)
    }

    fn lerp(v: [f32; 2], x: f64) -> f32 {
        let x = x as f32;
        v[0] + x * (v[1] - v[0])
    }
}

impl Interpolate for u8 {
    fn lerp(v: [u8; 2], x: f64) -> u8 {
        Interpolate::lerp([v[0] as f64, v[1] as f64], x) as u8
    }

    fn bilerp(v: [[u8; 2]; 2], x: f64, y: f64) -> u8 {
        let array = [
            [v[0][0] as f64, v[0][1] as f64],
            [v[1][0] as f64, v[1][1] as f64],
        ];
        Interpolate::bilerp(array, x, y) as u8
    }
}

// TODO: Implement interpolate trait for all types that it is useful for. We might have to do some
// macro magic to do this without too much code duplication.

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

    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    struct Rgb {
        r: u8,
        g: u8,
        b: u8,
    }

    impl Interpolate for Rgb {
        fn lerp(v: [Rgb; 2], x: f64) -> Rgb {
            Rgb {
                r: u8::lerp([v[0].r, v[1].r], x),
                g: u8::lerp([v[0].g, v[1].g], x),
                b: u8::lerp([v[0].b, v[1].b], x)
            }
        }
    }

    // Test that we get the right result for a basic type
    #[test]
    fn basic_lerp_test() {
        let result = f32::lerp([0.0, 100.0], 0.5);
        assert!(49.9 < result && result < 50.1);
    }

    // Test that an implementation for a custom type works
    #[test]
    fn custom_type_lerp_test() {
        let start = Rgb { r: 0, g: 255, b: 0 };
        let end = Rgb { r: 100, g: 0, b: 200 };
        assert_eq!(Rgb::lerp([start, end], 0.5), Rgb { r: 50, g: 127, b: 100 });
    }
}<commit_msg>Implement interpolation for more types<commit_after>pub trait Interpolate: Clone {
    #[inline]
    fn bilerp(v: [[Self; 2]; 2], x: f64, y: f64) -> Self {
        let v0 = Interpolate::lerp([v[0][0].clone(), v[0][1].clone()], y);
        let v1 = Interpolate::lerp([v[1][0].clone(), v[1][1].clone()], y);
        Interpolate::lerp([v0, v1], x)
    }

    #[inline]
    fn lerp(v: [Self; 2], x: f64) -> Self;
}

impl Interpolate for f64 {
    fn bilerp(v: [[f64; 2]; 2], x: f64, y: f64) -> f64 {
        v[0][0]*(1.0-x)*(1.0-y) + v[1][0]*x*(1.0-y) + v[0][1]*(1.0-x)*y + v[1][1]*x*y
    }

    fn lerp(v: [f64; 2], x: f64) -> f64 {
        v[0] + x * (v[1] - v[0])
    }
}

impl Interpolate for f32 {
    fn bilerp(v: [[f32; 2]; 2], x: f64, y: f64) -> f32 {
        let x = x as f32;
        let y = y as f32;
        (v[0][0]*(1.0-x)*(1.0-y) + v[1][0]*x*(1.0-y) + v[0][1]*(1.0-x)*y + v[1][1]*x*y)
    }

    fn lerp(v: [f32; 2], x: f64) -> f32 {
        let x = x as f32;
        v[0] + x * (v[1] - v[0])
    }
}

macro_rules! impl_interpolate {
    ($src_type:ty, $dest_type:ty) => (
        impl Interpolate for $src_type {
            fn lerp(v: [$src_type; 2], x: f64) -> $src_type {
                Interpolate::lerp([v[0] as $dest_type, v[1] as $dest_type], x) as $src_type
            }
        }
    )
}

impl_interpolate!(u8, f32);
impl_interpolate!(u16, f32);
impl_interpolate!(u32, f64);
impl_interpolate!(u64, f64);

impl_interpolate!(i8, f32);
impl_interpolate!(i16, f32);
impl_interpolate!(i32, f64);
impl_interpolate!(i64, f64);

/// Performs linear interpolation between the elements of two arrays.
pub fn interpolate_array<T: Interpolate>(input: [&[T]; 2], output: &mut [T], x: f64) {
    for (output, (a, b)) in output.iter_mut().zip(input[0].iter().zip(input[1].iter())) {
        *output = Interpolate::lerp([a.clone(), b.clone()], x);
    }
}

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

    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    struct Rgb {
        r: u8,
        g: u8,
        b: u8,
    }

    impl Interpolate for Rgb {
        fn lerp(v: [Rgb; 2], x: f64) -> Rgb {
            Rgb {
                r: u8::lerp([v[0].r, v[1].r], x),
                g: u8::lerp([v[0].g, v[1].g], x),
                b: u8::lerp([v[0].b, v[1].b], x)
            }
        }
    }

    // Test that we get the right result for a basic type
    #[test]
    fn basic_lerp_test() {
        let result = f32::lerp([0.0, 100.0], 0.5);
        assert!(49.9 < result && result < 50.1);
    }

    // Test that an implementation for a custom type works
    #[test]
    fn custom_type_lerp_test() {
        let start = Rgb { r: 0, g: 255, b: 0 };
        let end = Rgb { r: 100, g: 0, b: 200 };
        assert_eq!(Rgb::lerp([start, end], 0.5), Rgb { r: 50, g: 127, b: 100 });
    }

    // Test that interpolating arrays works correctly
    #[test]
    fn interpolate_array_test() {
        let start = [0, 255, 0];
        let end = [100, 0, 200];

        let mut output = [0; 3];
        interpolate_array([&start, &end], &mut output, 0.5);

        assert_eq!(output, [50, 127, 100]);
    }
}
<|endoftext|>