<commit_before>//! Draw image

use internal;
use triangulation;
use Graphics;
use Color;
use ImageSize;
use DrawState;
use math::Matrix2d;

/// An image
#[derive(Copy, Clone)]
pub struct Image {
    /// The color
    pub color: Option<internal::Color>,
    /// The rectangle to draw image inside
    pub rectangle: Option<internal::Rectangle>,
    /// The image source rectangle
    pub source_rectangle: Option<internal::SourceRectangle>,
}

impl Image {
    /// Creates a new image
    pub fn new() -> Image {
        Image {
            color: None,
            source_rectangle: None,
            rectangle: None,
        }
    }

    /// Creates a new colored image
    pub fn new_colored(color: internal::Color) -> Image {
        Image {
            color: Some(color),
            source_rectangle: None,
            rectangle: None
        }
    }

    /// Draws the image.
    pub fn draw<G>(
        &self,
        texture: &<G as Graphics>::Texture,
        draw_state: &DrawState,
        transform: Matrix2d,
        g: &mut G
    )
        where G: Graphics
    {
        use math::Scalar;

        let color = self.color.unwrap_or([1.0; 4]);
        let source_rectangle = self.source_rectangle.unwrap_or({
            let (w, h) = texture.get_size();
            [0, 0, w as i32, h as i32]
        });
        let rectangle = self.rectangle.unwrap_or([
            0.0,
            0.0,
            source_rectangle[2] as Scalar,
            source_rectangle[3] as Scalar
        ]);
        g.tri_list_uv(
            draw_state,
            &color,
            texture,
            |f| f(
                &triangulation::rect_tri_list_xy(transform, rectangle),
                &triangulation::rect_tri_list_uv(texture, source_rectangle)
            )
        );
    }
}

/*
quack! {
    img: Image[]
    get:
    set:
        fn (val: Color) [] { img.color = Some(val.0) }
        fn (val: Rect) [] { img.rectangle = Some(val.0) }
        fn (val: SrcRect) [] { img.source_rectangle = Some(val.0) }
    action:
}
*/

#[cfg(test)]
mod test {
    use super::Image;
    use Color;
    use Rect;
    use SrcRect;

    #[test]
    fn test_image() {
        let _img = Image::new()
            .set(Color([1.0; 4]))
            .set(Rect([0.0, 0.0, 100.0, 100.0]))
            .set(SrcRect([0, 0, 32, 32]));
    }
}
<commit_msg>Added builder methods to `Image`<commit_after>//! Draw image

use internal;
use triangulation;
use Graphics;
use Color;
use ImageSize;
use DrawState;
use math::Matrix2d;

/// An image
#[derive(Copy, Clone)]
pub struct Image {
    /// The color
    pub color: Option<internal::Color>,
    /// The rectangle to draw image inside
    pub rectangle: Option<internal::Rectangle>,
    /// The image source rectangle
    pub source_rectangle: Option<internal::SourceRectangle>,
}

impl Image {
    /// Creates a new image
    pub fn new() -> Image {
        Image {
            color: None,
            source_rectangle: None,
            rectangle: None,
        }
    }

    /// Creates a new colored image
    pub fn new_colored(color: internal::Color) -> Image {
        Image {
            color: Some(color),
            source_rectangle: None,
            rectangle: None
        }
    }

    /// Sets color.
    pub fn color(mut self, value: internal::Color) -> Self {
        self.color = Some(value);
        self
    }

    /// Sets optional color.
    pub fn maybe_color(mut self, value: Option<internal::Color>) -> Self {
        self.color = value;
        self
    }

    /// Sets rectangle.
    pub fn rect(mut self, value: internal::Rectangle) -> Self {
        self.rectangle = Some(value);
        self
    }

    /// Sets optional rectangle.
    pub fn maybe_rect(mut self, value: Option<internal::Rectangle>) -> Self {
        self.rectangle = value;
        self
    }

    /// Sets source rectangle.
    pub fn src_rect(mut self, value: internal::SourceRectangle) -> Self {
        self.source_rectangle = Some(value);
        self
    }

    /// Sets optional source rectangle.
    pub fn maybe_src_rect(mut self, value: Option<internal::SourceRectangle>) -> Self {
        self.source_rectangle = value;
        self
    }

    /// Draws the image.
    pub fn draw<G>(
        &self,
        texture: &<G as Graphics>::Texture,
        draw_state: &DrawState,
        transform: Matrix2d,
        g: &mut G
    )
        where G: Graphics
    {
        use math::Scalar;

        let color = self.color.unwrap_or([1.0; 4]);
        let source_rectangle = self.source_rectangle.unwrap_or({
            let (w, h) = texture.get_size();
            [0, 0, w as i32, h as i32]
        });
        let rectangle = self.rectangle.unwrap_or([
            0.0,
            0.0,
            source_rectangle[2] as Scalar,
            source_rectangle[3] as Scalar
        ]);
        g.tri_list_uv(
            draw_state,
            &color,
            texture,
            |f| f(
                &triangulation::rect_tri_list_xy(transform, rectangle),
                &triangulation::rect_tri_list_uv(texture, source_rectangle)
            )
        );
    }
}

#[cfg(test)]
mod test {
    use super::Image;
    use Color;
    use Rect;
    use SrcRect;

    #[test]
    fn test_image() {
        let _img = Image::new()
            .color([1.0; 4])
            .rect([0.0, 0.0, 100.0, 100.0])
            .src_rect([0, 0, 32, 32]);
    }
}
<|endoftext|>


<commit_before>//! ICWS '94 draft
//!

use std::cmp::PartialEq;
use std::default::Default;
use std::ops::{Index, IndexMut};

// #[derive(Clone, Copy, Debug, Default)]
// pub struct Address(u32);
pub type Address = u32;

#[derive(Clone, Copy, Debug)]
pub enum Opcode {
    DAT, // terminate process
    MOV, // move from A to B
    ADD, // add A to B, store result in B
    SUB, // subtract A from B, store result in B
    MUL, // multiply A by B, store result in B
    DIV, // divide B by A, store result in B if A <> 0, else terminate
    MOD, // divide B by A, store remainder in B if A <> 0, else terminate
    JMP, // transfer execution to A
    JMZ, // transfer execution to A if B is zero
    JMN, // transfer execution to A if B is non-zero
    DJN, // decrement B, if B is non-zero, transfer execution to A
    CMP, // same as SEQ
    SLT, // skip next instruction if A is less than B
    SPL, // split off process to A
    SEQ, // (*) Skip next instruction if A is equal to B
    SNE, // (*) Skip next instruction if A is not equal to B
    NOP, // (*) No operation
    LDP, // (+) Load P-space cell A into core address B
    STP, // (+) Store A-number into P-space cell B
}

impl Default for Opcode {
    fn default() -> Self {
        Opcode::DAT
    }
}

#[derive(Clone, Copy, Debug)]
pub enum Modifier {
    A,
    B,
    AB,
    BA,
    F,
    X,
    I,
}

impl Default for Modifier {
    fn default() -> Self {
        Modifier::A
    }
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Mode {
    IMMEDIATE, // #
    DIRECT, // $ (Default)
    INDIRECT, // @
    DECREMENT, // <
    INCREMENT, // >
}

impl Default for Mode {
    fn default() -> Self {
        Mode::IMMEDIATE
    }
}

#[derive(Clone, Copy, Debug, Default)]
pub struct Instruction {
    pub opcode: Opcode,
    pub modifier: Modifier,
    pub a_mode: Mode,
    pub a_number: Address,
    pub b_mode: Mode,
    pub b_number: Address,
}

impl Instruction {
    pub fn random() -> Self {
        Instruction::default()  // XXX Need real random implementation
    }
}

#[derive(Clone, Copy, Debug, Default)]
pub struct Warrior(u32);

#[derive(Debug)]
pub struct TaskQueue {
    task_limit: usize,
    task_pointer: Vec<Address>,
}

impl TaskQueue {
    fn new(limit: usize) -> Self {
        TaskQueue {
            task_limit: limit,
            task_pointer: Vec::<Address>::with_capacity(limit),
        }
    }

    pub fn queue(&mut self, addr: Address) {
        if self.task_pointer.len() < self.task_limit {
            self.task_pointer.push(addr);
        }
    }

    pub fn next(&mut self) -> Option<Address> {
        if self.task_pointer.len() > 0 {
            Some(self.task_pointer.remove(0))
        } else {
            None
        }
    }
}

#[derive(Debug)]
struct CoreMemory(Vec<Instruction>);

impl Index<Address> for CoreMemory {
    type Output = Instruction;

    fn index<'a>(&'a self, _index: Address) -> &'a Instruction {
        &self.0[_index as usize]
    }
}

impl IndexMut<Address> for CoreMemory {
    fn index_mut<'a>(&'a mut self, _index: Address) -> &'a mut Instruction {
        &mut self.0[_index as usize]
    }
}

#[derive(Debug)]
pub struct Core {
    core_size: Address,
    core: CoreMemory,
    warrior: [TaskQueue; 2],
    pc: Address,
    read_limit: Address,
    write_limit: Address,
}

impl Core {
    pub fn queue(&mut self, warrior: usize, task_pointer: Address) {
        self.warrior[warrior].queue(task_pointer)
    }

    fn fold(&self, pointer: Address, limit: Address) -> Address {
        let mut result = pointer % limit;
        if result > limit / 2 {
            result += self.core_size - limit;
        }
        result
    }

    pub fn emi94(&mut self) {
        let ir: Instruction;
        let ira: Instruction;
        let irb: Instruction;
        let mut rpa: Address;
        let mut wpa: Address;
        let rpb: Address;
        let wpb: Address;
        let pip: Address;

        ir = self.core[self.pc];

        // Evaluate A-operand
        //
        if ir.a_mode == Mode::IMMEDIATE {
            // For instructions with an Immediate A-mode, the Pointer A
            // points to the source of the current instruction.
            rpa = 0;
            wpa = 0;
        } else {
            // For instructions with a Direct A-mode, the Pointer A
            // points to the instruction IR.ANumber away, relative to
            // the Program Counter.
            rpa = self.fold(ir.a_number, self.read_limit);
            wpa = self.fold(ir.a_number, self.write_limit);

            if ir.a_mode != Mode::DIRECT {
                if ir.a_mode == Mode::DECREMENT {
                    self.core[((self.pc + wpa) % self.core_size)].b_number =
                        (self.core[((self.pc + wpa) % self.core_size)].b_number +
                         self.core_size - 1) % self.core_size;
                }

                if ir.a_mode == Mode::INCREMENT {
                    pip = (self.pc + wpa) % self.core_size;
                }

                rpa = self.fold((rpa + self.core[((self.pc + rpa) % self.core_size)].b_number),
                                self.read_limit);
                wpa = self.fold((wpa + self.core[((self.pc + wpa) % self.core_size)].b_number),
                                self.write_limit);
            }
        }

    }
}

#[derive(Debug)]
pub enum InitialInstruction {
    Default,
    Random,
    Instruction(Instruction),
}

#[derive(Debug)]
pub struct CoreBuilder {
    core_size: u32,
    initial_instruction: InitialInstruction,
    task_limit: usize,
}

impl CoreBuilder {
    pub fn new() -> Self {
        CoreBuilder {
            core_size: 8192,
            initial_instruction: InitialInstruction::Default,
            task_limit: 64,
        }
    }

    pub fn coresize(&mut self, size: u32) -> &Self {
        self.core_size = size;
        self
    }

    pub fn initial_instruction(&mut self, insn: InitialInstruction) -> &Self {
        self.initial_instruction = insn;
        self
    }

    pub fn task_limit(&mut self, limit: usize) -> &Self {
        self.task_limit = limit;
        self
    }

    pub fn build(&self) -> Core {
        let mut instructions = Vec::<Instruction>::new();
        for _ in 0..self.core_size {
            instructions.push(match self.initial_instruction {
                InitialInstruction::Default => Instruction::default(),
                InitialInstruction::Random => Instruction::random(),
                InitialInstruction::Instruction(insn) => insn,
            })
        }

        Core {
            core_size: self.core_size,
            core: CoreMemory(instructions),
            warrior: [TaskQueue::new(self.task_limit), TaskQueue::new(self.task_limit)],
            pc: 0,
            read_limit: 300,
            write_limit: 300,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn task_queue_simple() {
        let mut tq = TaskQueue::new(2);
        tq.queue(1);
        tq.queue(3);
        assert_eq!(tq.next(), Some(1));
        assert_eq!(tq.next(), Some(3));
        assert_eq!(tq.next(), None);
    }

    #[test]
    fn task_queue_limit() {
        let mut tq = TaskQueue::new(3);
        tq.queue(100);
        tq.queue(200);
        tq.queue(300);
        tq.queue(400);

        assert_eq!(tq.next(), Some(100));
        assert_eq!(tq.next(), Some(200));
        assert_eq!(tq.next(), Some(300));
        assert_eq!(tq.next(), None);
    }

    #[test]
    fn task_queue_empty() {
        let mut tq = TaskQueue::new(100);

        assert_eq!(tq.next(), None);
    }
}
<commit_msg>Drop unused/superfluos trait imports<commit_after>//! ICWS '94 draft
//!

use std::ops::{Index, IndexMut};

// #[derive(Clone, Copy, Debug, Default)]
// pub struct Address(u32);
pub type Address = u32;

#[derive(Clone, Copy, Debug)]
pub enum Opcode {
    DAT, // terminate process
    MOV, // move from A to B
    ADD, // add A to B, store result in B
    SUB, // subtract A from B, store result in B
    MUL, // multiply A by B, store result in B
    DIV, // divide B by A, store result in B if A <> 0, else terminate
    MOD, // divide B by A, store remainder in B if A <> 0, else terminate
    JMP, // transfer execution to A
    JMZ, // transfer execution to A if B is zero
    JMN, // transfer execution to A if B is non-zero
    DJN, // decrement B, if B is non-zero, transfer execution to A
    CMP, // same as SEQ
    SLT, // skip next instruction if A is less than B
    SPL, // split off process to A
    SEQ, // (*) Skip next instruction if A is equal to B
    SNE, // (*) Skip next instruction if A is not equal to B
    NOP, // (*) No operation
    LDP, // (+) Load P-space cell A into core address B
    STP, // (+) Store A-number into P-space cell B
}

impl Default for Opcode {
    fn default() -> Self {
        Opcode::DAT
    }
}

#[derive(Clone, Copy, Debug)]
pub enum Modifier {
    A,
    B,
    AB,
    BA,
    F,
    X,
    I,
}

impl Default for Modifier {
    fn default() -> Self {
        Modifier::A
    }
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Mode {
    IMMEDIATE, // #
    DIRECT, // $ (Default)
    INDIRECT, // @
    DECREMENT, // <
    INCREMENT, // >
}

impl Default for Mode {
    fn default() -> Self {
        Mode::IMMEDIATE
    }
}

#[derive(Clone, Copy, Debug, Default)]
pub struct Instruction {
    pub opcode: Opcode,
    pub modifier: Modifier,
    pub a_mode: Mode,
    pub a_number: Address,
    pub b_mode: Mode,
    pub b_number: Address,
}

impl Instruction {
    pub fn random() -> Self {
        Instruction::default()  // XXX Need real random implementation
    }
}

#[derive(Clone, Copy, Debug, Default)]
pub struct Warrior(u32);

#[derive(Debug)]
pub struct TaskQueue {
    task_limit: usize,
    task_pointer: Vec<Address>,
}

impl TaskQueue {
    fn new(limit: usize) -> Self {
        TaskQueue {
            task_limit: limit,
            task_pointer: Vec::<Address>::with_capacity(limit),
        }
    }

    pub fn queue(&mut self, addr: Address) {
        if self.task_pointer.len() < self.task_limit {
            self.task_pointer.push(addr);
        }
    }

    pub fn next(&mut self) -> Option<Address> {
        if self.task_pointer.len() > 0 {
            Some(self.task_pointer.remove(0))
        } else {
            None
        }
    }
}

#[derive(Debug)]
struct CoreMemory(Vec<Instruction>);

impl Index<Address> for CoreMemory {
    type Output = Instruction;

    fn index<'a>(&'a self, _index: Address) -> &'a Instruction {
        &self.0[_index as usize]
    }
}

impl IndexMut<Address> for CoreMemory {
    fn index_mut<'a>(&'a mut self, _index: Address) -> &'a mut Instruction {
        &mut self.0[_index as usize]
    }
}

#[derive(Debug)]
pub struct Core {
    core_size: Address,
    core: CoreMemory,
    warrior: [TaskQueue; 2],
    pc: Address,
    read_limit: Address,
    write_limit: Address,
}

impl Core {
    pub fn queue(&mut self, warrior: usize, task_pointer: Address) {
        self.warrior[warrior].queue(task_pointer)
    }

    fn fold(&self, pointer: Address, limit: Address) -> Address {
        let mut result = pointer % limit;
        if result > limit / 2 {
            result += self.core_size - limit;
        }
        result
    }

    pub fn emi94(&mut self) {
        let ir: Instruction;
        let ira: Instruction;
        let irb: Instruction;
        let mut rpa: Address;
        let mut wpa: Address;
        let rpb: Address;
        let wpb: Address;
        let pip: Address;

        ir = self.core[self.pc];

        // Evaluate A-operand
        //
        if ir.a_mode == Mode::IMMEDIATE {
            // For instructions with an Immediate A-mode, the Pointer A
            // points to the source of the current instruction.
            rpa = 0;
            wpa = 0;
        } else {
            // For instructions with a Direct A-mode, the Pointer A
            // points to the instruction IR.ANumber away, relative to
            // the Program Counter.
            rpa = self.fold(ir.a_number, self.read_limit);
            wpa = self.fold(ir.a_number, self.write_limit);

            if ir.a_mode != Mode::DIRECT {
                if ir.a_mode == Mode::DECREMENT {
                    self.core[((self.pc + wpa) % self.core_size)].b_number =
                        (self.core[((self.pc + wpa) % self.core_size)].b_number +
                         self.core_size - 1) % self.core_size;
                }

                if ir.a_mode == Mode::INCREMENT {
                    pip = (self.pc + wpa) % self.core_size;
                }

                rpa = self.fold((rpa + self.core[((self.pc + rpa) % self.core_size)].b_number),
                                self.read_limit);
                wpa = self.fold((wpa + self.core[((self.pc + wpa) % self.core_size)].b_number),
                                self.write_limit);
            }
        }

    }
}

#[derive(Debug)]
pub enum InitialInstruction {
    Default,
    Random,
    Instruction(Instruction),
}

#[derive(Debug)]
pub struct CoreBuilder {
    core_size: u32,
    initial_instruction: InitialInstruction,
    task_limit: usize,
}

impl CoreBuilder {
    pub fn new() -> Self {
        CoreBuilder {
            core_size: 8192,
            initial_instruction: InitialInstruction::Default,
            task_limit: 64,
        }
    }

    pub fn coresize(&mut self, size: u32) -> &Self {
        self.core_size = size;
        self
    }

    pub fn initial_instruction(&mut self, insn: InitialInstruction) -> &Self {
        self.initial_instruction = insn;
        self
    }

    pub fn task_limit(&mut self, limit: usize) -> &Self {
        self.task_limit = limit;
        self
    }

    pub fn build(&self) -> Core {
        let mut instructions = Vec::<Instruction>::new();
        for _ in 0..self.core_size {
            instructions.push(match self.initial_instruction {
                InitialInstruction::Default => Instruction::default(),
                InitialInstruction::Random => Instruction::random(),
                InitialInstruction::Instruction(insn) => insn,
            })
        }

        Core {
            core_size: self.core_size,
            core: CoreMemory(instructions),
            warrior: [TaskQueue::new(self.task_limit), TaskQueue::new(self.task_limit)],
            pc: 0,
            read_limit: 300,
            write_limit: 300,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn task_queue_simple() {
        let mut tq = TaskQueue::new(2);
        tq.queue(1);
        tq.queue(3);
        assert_eq!(tq.next(), Some(1));
        assert_eq!(tq.next(), Some(3));
        assert_eq!(tq.next(), None);
    }

    #[test]
    fn task_queue_limit() {
        let mut tq = TaskQueue::new(3);
        tq.queue(100);
        tq.queue(200);
        tq.queue(300);
        tq.queue(400);

        assert_eq!(tq.next(), Some(100));
        assert_eq!(tq.next(), Some(200));
        assert_eq!(tq.next(), Some(300));
        assert_eq!(tq.next(), None);
    }

    #[test]
    fn task_queue_empty() {
        let mut tq = TaskQueue::new(100);

        assert_eq!(tq.next(), None);
    }
}
<|endoftext|>


<commit_before>use num::Float;
use std::fmt;
use std::ops::Mul;

use numvec::Vec3f;

/// The type of matrix elements.
pub type Scalar = f32;

/// A 4x4 matrix type stored in column-major order for interoperability with
/// OpenGL.
///
/// Supports the creation of isometries and projections in homogenous
/// coordinates.  In terms of operations, only transposition and multiplication
/// are currently supported (and not super-efficiently implemented).
///
/// _Note:_ The 16 elements are stored in place, so copies are not cheap.
#[packed]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Mat4 {
    data: [Scalar; 16]
}

impl Mat4 {
    pub fn new(m00: Scalar, m01: Scalar, m02: Scalar, m03: Scalar,
               m10: Scalar, m11: Scalar, m12: Scalar, m13: Scalar,
               m20: Scalar, m21: Scalar, m22: Scalar, m23: Scalar,
               m30: Scalar, m31: Scalar, m32: Scalar, m33: Scalar) -> Mat4 {
        // In my mind vectors are columns, hence matrices need to be transposed
        // to the OpenGL memory order.
        Mat4 { data: [m00, m10, m20, m30, m01, m11, m21, m31,
                      m02, m12, m22, m32, m03, m13, m23, m33] }
    }

    pub fn new_identity() -> Mat4 {
        Mat4::new(1.0, 0.0, 0.0, 0.0,
                  0.0, 1.0, 0.0, 0.0,
                  0.0, 0.0, 1.0, 0.0,
                  0.0, 0.0, 0.0, 1.0)
    }

    /// Creates a perspective projection matrix from.
    ///
    /// The parameters are:
    /// * `fov_degrees`  - Horizontal field of view.
    /// * `aspect_ratio` - Ratio between width and height of the view.
    /// * `near`, `far`  - The Z coordinate of the near and far planes.
    pub fn new_perspective(fov_degrees: Scalar, aspect_ratio: Scalar,
                           near: Scalar, far: Scalar) -> Mat4 {
        let fov = (3.1415926538 * fov_degrees) / 180.0;
        let f = 1.0 / (fov * 0.5).tan();

        Mat4::new(
            f / aspect_ratio, 0.0, 0.0, 0.0,
            0.0, f, 0.0, 0.0,
            0.0, 0.0, (far + near) / (near - far), 2.0*far*near / (near - far),
            0.0, 0.0, -1.0, 0.0)
    }

    /// Creates a matrix which rotates points by `angle_radians` around `axis`.
    pub fn new_axis_rotation(axis: &Vec3f, angle_radians: Scalar) -> Mat4 {
        let ca = angle_radians.cos();
        let sa = angle_radians.sin();
        let nca = 1.0 - ca;
        let u = axis;
        Mat4::new(
            ca + u.x*u.x*nca, u.x*u.y*nca - u.z*sa, u.x*u.z*nca + u.y*sa, 0.0,
            u.y*u.x*nca + u.z*sa, ca + u.y*u.y*nca, u.y*u.z*nca - u.x*sa, 0.0,
            u.z*u.x*nca - u.y*sa, u.z*u.y*nca + u.x*sa, ca + u.z*u.z*nca, 0.0,
            0.0, 0.0, 0.0, 1.0
        )
    }

    /// Creates a rotation matrix from the three _Euler angles_.
    pub fn new_euler_rotation(yaw: f32, pitch: f32, roll: f32) -> Mat4 {
        let (ca, sa) = (yaw.cos(), yaw.sin());
        let (cb, sb) = (roll.cos(), roll.sin());
        let (cc, sc) = (pitch.cos(), pitch.sin());

        Mat4::new(
             ca*cb, sa*sc - ca*sb*cc,  ca*sb*sc + sa*cc, 0.0,
                sb,          cb * cc,          -cb * sc, 0.0,
            -sa*cb, sa*sb*cc + ca*sc, -sa*sb*sc + ca*cc, 0.0,
               0.0,              0.0,               0.0, 1.0,
        )
    }

    /// Creates a translation matrix which maps points `p` to `p + by`.
    pub fn new_translation(by: Vec3f) -> Mat4 {
        Mat4::new(1.0, 0.0, 0.0, by.x,
                  0.0, 1.0, 0.0, by.y,
                  0.0, 0.0, 1.0, by.z,
                  0.0, 0.0, 0.0,  1.0)
    }

    /// Returns the transpose of the matrix (columns swapped with rows).
    pub fn transposed(&self) -> Mat4 {
        let m = &self.data;
        // m is in column-major order, so calling with new in row-order will
        // transpose it.
        Mat4::new(m[0], m[1], m[2], m[3],
                  m[4], m[5], m[6], m[7],
                  m[8], m[9], m[10], m[11],
                  m[12], m[13], m[14], m[15])
    }

    pub fn get(&self, row: usize, column: usize) -> Scalar {
        self.data[column * 4 + row]
    }

    pub fn as_scalar_ptr(&self) -> *const Scalar {
        self.data.as_ptr()
    }
}

impl fmt::Debug for Mat4 {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter,
               "[{:10.3e} {:10.3e} {:10.3e} {:10.3e};\n \
                 {:10.3e} {:10.3e} {:10.3e} {:10.3e};\n \
                 {:10.3e} {:10.3e} {:10.3e} {:10.3e};\n \
                 {:10.3e} {:10.3e} {:10.3e} {:10.3e}]",
               self.get(0, 0), self.get(0, 1), self.get(0, 2), self.get(0, 3),
               self.get(1, 0), self.get(1, 1), self.get(1, 2), self.get(1, 3),
               self.get(2, 0), self.get(2, 1), self.get(2, 2), self.get(2, 3),
               self.get(3, 0), self.get(3, 1), self.get(3, 2), self.get(3, 3))
    }
}

impl Mul for Mat4 {
    type Output = Mat4;

    fn mul(self, rhs: Mat4) -> Mat4 {
        let l = &self.data;
        let r = &rhs.data;
        Mat4 { data:[
            l[ 0]*r[ 0] + l[ 4]*r[ 1] + l[ 8]*r[ 2] + l[12]*r[ 3],
            l[ 1]*r[ 0] + l[ 5]*r[ 1] + l[ 9]*r[ 2] + l[13]*r[ 3],
            l[ 2]*r[ 0] + l[ 6]*r[ 1] + l[10]*r[ 2] + l[14]*r[ 3],
            l[ 3]*r[ 0] + l[ 7]*r[ 1] + l[11]*r[ 2] + l[15]*r[ 3],

            l[ 0]*r[ 4] + l[ 4]*r[ 5] + l[ 8]*r[ 6] + l[12]*r[ 7],
            l[ 1]*r[ 4] + l[ 5]*r[ 5] + l[ 9]*r[ 6] + l[13]*r[ 7],
            l[ 2]*r[ 4] + l[ 6]*r[ 5] + l[10]*r[ 6] + l[14]*r[ 7],
            l[ 3]*r[ 4] + l[ 7]*r[ 5] + l[11]*r[ 6] + l[15]*r[ 7],

            l[ 0]*r[ 8] + l[ 4]*r[ 9] + l[ 8]*r[10] + l[12]*r[11],
            l[ 1]*r[ 8] + l[ 5]*r[ 9] + l[ 9]*r[10] + l[13]*r[11],
            l[ 2]*r[ 8] + l[ 6]*r[ 9] + l[10]*r[10] + l[14]*r[11],
            l[ 3]*r[ 8] + l[ 7]*r[ 9] + l[11]*r[10] + l[15]*r[11],

            l[ 0]*r[12] + l[ 4]*r[13] + l[ 8]*r[14] + l[12]*r[15],
            l[ 1]*r[12] + l[ 5]*r[13] + l[ 9]*r[14] + l[13]*r[15],
            l[ 2]*r[12] + l[ 6]*r[13] + l[10]*r[14] + l[14]*r[15],
            l[ 3]*r[12] + l[ 7]*r[13] + l[11]*r[14] + l[15]*r[15],
        ]}
    }
}

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

    #[test]
    fn test_mul() {
        use std::num::Float;
        let a = Mat4::new(4.0,    8.0,    1.0,    6.0,
                          9.0,    4.0,    2.0,    1.0,
                          4.0,    3.0,    9.0,    3.0,
                          2.0,    4.0,    9.0,    4.0);

        let b = Mat4::new(8.0,    6.0,    5.0,    7.0,
                          1.0,    7.0,    3.0,    2.0,
                          1.0,    6.0,    7.0,    4.0,
                          2.0,    5.0,    2.0,    6.0);

        let exp_ab = Mat4::new(53.0,   116.0,    63.0,    84.0,
                               80.0,    99.0,    73.0,    85.0,
                               50.0,   114.0,    98.0,    88.0,
                               37.0,   114.0,    93.0,    82.0);
        let ab = a * b;

        for i in 0..16 {
            if exp_ab.data[i] != ab.data[i] {
                panic!(
                    "They differ at {} ({}):\nexpected=\n{:?}\n\nactual=\n{:?}",
                    i, (a.data[i] - b.data[i]).abs(), exp_ab, ab);
            }
        }

    }
}
<commit_msg>Fixed math test<commit_after>use num::Float;
use std::fmt;
use std::ops::Mul;

use numvec::Vec3f;

/// The type of matrix elements.
pub type Scalar = f32;

/// A 4x4 matrix type stored in column-major order for interoperability with
/// OpenGL.
///
/// Supports the creation of isometries and projections in homogenous
/// coordinates.  In terms of operations, only transposition and multiplication
/// are currently supported (and not super-efficiently implemented).
///
/// _Note:_ The 16 elements are stored in place, so copies are not cheap.
#[packed]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Mat4 {
    data: [Scalar; 16]
}

impl Mat4 {
    pub fn new(m00: Scalar, m01: Scalar, m02: Scalar, m03: Scalar,
               m10: Scalar, m11: Scalar, m12: Scalar, m13: Scalar,
               m20: Scalar, m21: Scalar, m22: Scalar, m23: Scalar,
               m30: Scalar, m31: Scalar, m32: Scalar, m33: Scalar) -> Mat4 {
        // In my mind vectors are columns, hence matrices need to be transposed
        // to the OpenGL memory order.
        Mat4 { data: [m00, m10, m20, m30, m01, m11, m21, m31,
                      m02, m12, m22, m32, m03, m13, m23, m33] }
    }

    pub fn new_identity() -> Mat4 {
        Mat4::new(1.0, 0.0, 0.0, 0.0,
                  0.0, 1.0, 0.0, 0.0,
                  0.0, 0.0, 1.0, 0.0,
                  0.0, 0.0, 0.0, 1.0)
    }

    /// Creates a perspective projection matrix from.
    ///
    /// The parameters are:
    /// * `fov_degrees`  - Horizontal field of view.
    /// * `aspect_ratio` - Ratio between width and height of the view.
    /// * `near`, `far`  - The Z coordinate of the near and far planes.
    pub fn new_perspective(fov_degrees: Scalar, aspect_ratio: Scalar,
                           near: Scalar, far: Scalar) -> Mat4 {
        let fov = (3.1415926538 * fov_degrees) / 180.0;
        let f = 1.0 / (fov * 0.5).tan();

        Mat4::new(
            f / aspect_ratio, 0.0, 0.0, 0.0,
            0.0, f, 0.0, 0.0,
            0.0, 0.0, (far + near) / (near - far), 2.0*far*near / (near - far),
            0.0, 0.0, -1.0, 0.0)
    }

    /// Creates a matrix which rotates points by `angle_radians` around `axis`.
    pub fn new_axis_rotation(axis: &Vec3f, angle_radians: Scalar) -> Mat4 {
        let ca = angle_radians.cos();
        let sa = angle_radians.sin();
        let nca = 1.0 - ca;
        let u = axis;
        Mat4::new(
            ca + u.x*u.x*nca, u.x*u.y*nca - u.z*sa, u.x*u.z*nca + u.y*sa, 0.0,
            u.y*u.x*nca + u.z*sa, ca + u.y*u.y*nca, u.y*u.z*nca - u.x*sa, 0.0,
            u.z*u.x*nca - u.y*sa, u.z*u.y*nca + u.x*sa, ca + u.z*u.z*nca, 0.0,
            0.0, 0.0, 0.0, 1.0
        )
    }

    /// Creates a rotation matrix from the three _Euler angles_.
    pub fn new_euler_rotation(yaw: f32, pitch: f32, roll: f32) -> Mat4 {
        let (ca, sa) = (yaw.cos(), yaw.sin());
        let (cb, sb) = (roll.cos(), roll.sin());
        let (cc, sc) = (pitch.cos(), pitch.sin());

        Mat4::new(
             ca*cb, sa*sc - ca*sb*cc,  ca*sb*sc + sa*cc, 0.0,
                sb,          cb * cc,          -cb * sc, 0.0,
            -sa*cb, sa*sb*cc + ca*sc, -sa*sb*sc + ca*cc, 0.0,
               0.0,              0.0,               0.0, 1.0,
        )
    }

    /// Creates a translation matrix which maps points `p` to `p + by`.
    pub fn new_translation(by: Vec3f) -> Mat4 {
        Mat4::new(1.0, 0.0, 0.0, by.x,
                  0.0, 1.0, 0.0, by.y,
                  0.0, 0.0, 1.0, by.z,
                  0.0, 0.0, 0.0,  1.0)
    }

    /// Returns the transpose of the matrix (columns swapped with rows).
    pub fn transposed(&self) -> Mat4 {
        let m = &self.data;
        // m is in column-major order, so calling with new in row-order will
        // transpose it.
        Mat4::new(m[0], m[1], m[2], m[3],
                  m[4], m[5], m[6], m[7],
                  m[8], m[9], m[10], m[11],
                  m[12], m[13], m[14], m[15])
    }

    pub fn get(&self, row: usize, column: usize) -> Scalar {
        self.data[column * 4 + row]
    }

    pub fn as_scalar_ptr(&self) -> *const Scalar {
        self.data.as_ptr()
    }
}

impl fmt::Debug for Mat4 {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter,
               "[{:10.3e} {:10.3e} {:10.3e} {:10.3e};\n \
                 {:10.3e} {:10.3e} {:10.3e} {:10.3e};\n \
                 {:10.3e} {:10.3e} {:10.3e} {:10.3e};\n \
                 {:10.3e} {:10.3e} {:10.3e} {:10.3e}]",
               self.get(0, 0), self.get(0, 1), self.get(0, 2), self.get(0, 3),
               self.get(1, 0), self.get(1, 1), self.get(1, 2), self.get(1, 3),
               self.get(2, 0), self.get(2, 1), self.get(2, 2), self.get(2, 3),
               self.get(3, 0), self.get(3, 1), self.get(3, 2), self.get(3, 3))
    }
}

impl Mul for Mat4 {
    type Output = Mat4;

    fn mul(self, rhs: Mat4) -> Mat4 {
        let l = &self.data;
        let r = &rhs.data;
        Mat4 { data:[
            l[ 0]*r[ 0] + l[ 4]*r[ 1] + l[ 8]*r[ 2] + l[12]*r[ 3],
            l[ 1]*r[ 0] + l[ 5]*r[ 1] + l[ 9]*r[ 2] + l[13]*r[ 3],
            l[ 2]*r[ 0] + l[ 6]*r[ 1] + l[10]*r[ 2] + l[14]*r[ 3],
            l[ 3]*r[ 0] + l[ 7]*r[ 1] + l[11]*r[ 2] + l[15]*r[ 3],

            l[ 0]*r[ 4] + l[ 4]*r[ 5] + l[ 8]*r[ 6] + l[12]*r[ 7],
            l[ 1]*r[ 4] + l[ 5]*r[ 5] + l[ 9]*r[ 6] + l[13]*r[ 7],
            l[ 2]*r[ 4] + l[ 6]*r[ 5] + l[10]*r[ 6] + l[14]*r[ 7],
            l[ 3]*r[ 4] + l[ 7]*r[ 5] + l[11]*r[ 6] + l[15]*r[ 7],

            l[ 0]*r[ 8] + l[ 4]*r[ 9] + l[ 8]*r[10] + l[12]*r[11],
            l[ 1]*r[ 8] + l[ 5]*r[ 9] + l[ 9]*r[10] + l[13]*r[11],
            l[ 2]*r[ 8] + l[ 6]*r[ 9] + l[10]*r[10] + l[14]*r[11],
            l[ 3]*r[ 8] + l[ 7]*r[ 9] + l[11]*r[10] + l[15]*r[11],

            l[ 0]*r[12] + l[ 4]*r[13] + l[ 8]*r[14] + l[12]*r[15],
            l[ 1]*r[12] + l[ 5]*r[13] + l[ 9]*r[14] + l[13]*r[15],
            l[ 2]*r[12] + l[ 6]*r[13] + l[10]*r[14] + l[14]*r[15],
            l[ 3]*r[12] + l[ 7]*r[13] + l[11]*r[14] + l[15]*r[15],
        ]}
    }
}

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

    #[test]
    fn test_mul() {
        let a = Mat4::new(4.0,    8.0,    1.0,    6.0,
                          9.0,    4.0,    2.0,    1.0,
                          4.0,    3.0,    9.0,    3.0,
                          2.0,    4.0,    9.0,    4.0);

        let b = Mat4::new(8.0,    6.0,    5.0,    7.0,
                          1.0,    7.0,    3.0,    2.0,
                          1.0,    6.0,    7.0,    4.0,
                          2.0,    5.0,    2.0,    6.0);

        let exp_ab = Mat4::new(53.0,   116.0,    63.0,    84.0,
                               80.0,    99.0,    73.0,    85.0,
                               50.0,   114.0,    98.0,    88.0,
                               37.0,   114.0,    93.0,    82.0);
        let ab = a * b;

        for i in 0..16 {
            if exp_ab.data[i] != ab.data[i] {
                panic!(
                    "They differ at {} ({}):\nexpected=\n{:?}\n\nactual=\n{:?}",
                    i, (a.data[i] - b.data[i]).abs(), exp_ab, ab);
            }
        }

    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
#![macro_use]

use std::fmt;
use std::iter::repeat;
use std::mem;
use std::ops::{
    Index,
};
use std::raw;
use num::traits::NumCast;
use Matrix;

#[derive(Debug, PartialEq)]
pub struct Mat<T> {
    rows: usize,
    cols: usize,
    data: Vec<T>,
}

impl<T> Mat<T> {
    pub fn new() -> Mat<T> {
        Mat {
            rows: 0,
            cols: 0,
            data: Vec::new(),
        }
    }

    pub fn rows(&self) -> usize { self.rows }
    pub fn cols(&self) -> usize { self.cols }
    pub unsafe fn set_rows(&mut self, n: usize) { self.rows = n; }
    pub unsafe fn set_cols(&mut self, n: usize) { self.cols = n; }

    pub unsafe fn push(&mut self, val: T) {
        self.data.push(val);
    }
}

impl<T: Clone> Mat<T> {
    pub fn fill(value: T, n: usize, m: usize) -> Mat<T> {
        Mat {
            rows: n,
            cols: m,
            data: repeat(value).take(n * m).collect(),
        }
    }
}

impl<T> Index<usize> for Mat<T> {
    type Output = [T];

    fn index<'a>(&'a self, index: usize) -> &'a [T] {
        let offset = (index * self.cols) as isize;

        unsafe {
            let ptr = (&self.data[..]).as_ptr().offset(offset);
            mem::transmute(raw::Slice { data: ptr, len: self.cols })
        }
    }
}

impl<T: fmt::Display> fmt::Display for Mat<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for i in 0usize..self.rows {
            for j in 0usize..self.cols {
                match write!(f, "{}", self[i][j]) {
                    Ok(_) => (),
                    x => return x,
                }
            }

            match writeln!(f, "") {
                Ok(_) => (),
                x => return x,
            }
        }

        Ok(())
    }
}

impl<T> Matrix<T> for Mat<T> {
    fn rows(&self) -> i32 {
        let n: Option<i32> = NumCast::from(self.rows);
        n.unwrap()
    }

    fn cols(&self) -> i32 {
        let n: Option<i32> = NumCast::from(self.cols);
        n.unwrap()
    }

    unsafe fn as_ptr(&self) -> *const T {
        self.data[..].as_ptr()
    }

    unsafe fn as_mut_ptr(&mut self) -> *mut T {
        (&mut self.data[..]).as_mut_ptr()
    }
}

#[macro_export]
macro_rules! mat(
    ($($($e: expr),+);*) => ({
        // leading _ to allow empty construction without a warning.
        let mut _temp = Mat::new();
        let mut rows = 0usize;
        let mut _cols;
        $(
            rows += 1;
            _cols = 0usize;
            $(
                _cols += 1;
                unsafe {
                    _temp.push($e);
                }
            )+
        )*

        unsafe {
            _temp.set_rows(rows);
            _temp.set_cols(_cols);
        }

        _temp
    });
);

#[cfg(test)]
mod tests {
    use math::Mat;

    #[test]
    fn index() {
        let a = mat![1f32, 2f32];
        assert_eq!(1.0, a[0][0]);
        assert_eq!(2.0, a[0][1]);

        let b = mat![1f32; 2f32];
        assert_eq!(1.0, b[0][0]);
        assert_eq!(2.0, b[1][0]);

        let m = mat![1f32, 2f32; 3f32, 4f32];
        assert_eq!(1.0, m[0][0]);
        assert_eq!(2.0, m[0][1]);
        assert_eq!(3.0, m[1][0]);
        assert_eq!(4.0, m[1][1]);
    }
}
<commit_msg>Make Mat::new accept dimensions<commit_after>// Copyright 2015 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
#![macro_use]

use std::fmt;
use std::iter::repeat;
use std::mem;
use std::ops::{
    Index,
};
use std::raw;
use num::traits::NumCast;
use Matrix;

#[derive(Debug, PartialEq)]
pub struct Mat<T> {
    rows: usize,
    cols: usize,
    data: Vec<T>,
}

impl<T> Mat<T> {
    pub fn new(n: usize, m: usize) -> Mat<T> {
        let len = n * m;
        let mut data = Vec::with_capacity(len);
        unsafe { data.set_len(len); }

        Mat {
            rows: n,
            cols: m,
            data: data,
        }
    }

    pub fn rows(&self) -> usize { self.rows }
    pub fn cols(&self) -> usize { self.cols }
    pub unsafe fn set_rows(&mut self, n: usize) { self.rows = n; }
    pub unsafe fn set_cols(&mut self, n: usize) { self.cols = n; }

    pub unsafe fn push(&mut self, val: T) {
        self.data.push(val);
    }
}

impl<T: Clone> Mat<T> {
    pub fn fill(value: T, n: usize, m: usize) -> Mat<T> {
        Mat {
            rows: n,
            cols: m,
            data: repeat(value).take(n * m).collect(),
        }
    }
}

impl<T> Index<usize> for Mat<T> {
    type Output = [T];

    fn index<'a>(&'a self, index: usize) -> &'a [T] {
        let offset = (index * self.cols) as isize;

        unsafe {
            let ptr = (&self.data[..]).as_ptr().offset(offset);
            mem::transmute(raw::Slice { data: ptr, len: self.cols })
        }
    }
}

impl<T: fmt::Display> fmt::Display for Mat<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for i in 0usize..self.rows {
            for j in 0usize..self.cols {
                match write!(f, "{}", self[i][j]) {
                    Ok(_) => (),
                    x => return x,
                }
            }

            match writeln!(f, "") {
                Ok(_) => (),
                x => return x,
            }
        }

        Ok(())
    }
}

impl<T> Matrix<T> for Mat<T> {
    fn rows(&self) -> i32 {
        let n: Option<i32> = NumCast::from(self.rows);
        n.unwrap()
    }

    fn cols(&self) -> i32 {
        let n: Option<i32> = NumCast::from(self.cols);
        n.unwrap()
    }

    unsafe fn as_ptr(&self) -> *const T {
        self.data[..].as_ptr()
    }

    unsafe fn as_mut_ptr(&mut self) -> *mut T {
        (&mut self.data[..]).as_mut_ptr()
    }
}

#[macro_export]
macro_rules! mat(
    ($($($e: expr),+);*) => ({
        // leading _ to allow empty construction without a warning.
        let mut _temp = Mat::new(0, 0);
        let mut rows = 0usize;
        let mut _cols;
        $(
            rows += 1;
            _cols = 0usize;
            $(
                _cols += 1;
                unsafe {
                    _temp.push($e);
                }
            )+
        )*

        unsafe {
            _temp.set_rows(rows);
            _temp.set_cols(_cols);
        }

        _temp
    });
);

#[cfg(test)]
mod tests {
    use math::Mat;

    #[test]
    fn index() {
        let a = mat![1f32, 2f32];
        assert_eq!(1.0, a[0][0]);
        assert_eq!(2.0, a[0][1]);

        let b = mat![1f32; 2f32];
        assert_eq!(1.0, b[0][0]);
        assert_eq!(2.0, b[1][0]);

        let m = mat![1f32, 2f32; 3f32, 4f32];
        assert_eq!(1.0, m[0][0]);
        assert_eq!(2.0, m[0][1]);
        assert_eq!(3.0, m[1][0]);
        assert_eq!(4.0, m[1][1]);
    }
}
<|endoftext|>


<commit_before>// information from https://raw.githubusercontent.com/torvalds/linux/master/
//                  /include/uapi/linux/can/error.h

use try_from::TryFrom;
use super::CanFrame;
use std::error::Error;
use std::{error, fmt};

#[inline]
/// Helper function to retrieve a specific byte of frame data or returning an
/// `Err(..)` otherwise.
fn get_data(frame: &CanFrame, idx: u8) -> Result<u8, CanErrorDecodingFailure> {
    Ok(*(frame.data().get(idx as usize).ok_or(CanErrorDecodingFailure::NotEnoughData(idx)))?)
}

/// Error decoding a CanError from a CanFrame.
#[derive(Copy, Clone, Debug)]
pub enum CanErrorDecodingFailure {
    /// The supplied CanFrame did not have the error bit set.
    NotAnError,

    /// The error type is not known and cannot be decoded.
    UnknownErrorType(u32),

    /// The error type indicated a need for additional information as `data`,
    /// but the `data` field was not long enough.
    NotEnoughData(u8),

    /// The error type `ControllerProblem` was indicated and additional
    /// information found, but not recognized.
    InvalidControllerProblem,

    /// The type of the ProtocolViolation was not valid
    InvalidViolationType,

    /// A location was specified for a ProtocolViolation, but the location
    /// was not valid.
    InvalidLocation,

    /// The supplied transciever error was invalid.
    InvalidTransceiverError,
}

impl error::Error for CanErrorDecodingFailure {
    fn description(&self) -> &str {
        match *self {
            CanErrorDecodingFailure::NotAnError => "CAN frame is not an error",
            CanErrorDecodingFailure::UnknownErrorType(_) => "unknown error type",
            CanErrorDecodingFailure::NotEnoughData(_) => "not enough data",
            CanErrorDecodingFailure::InvalidControllerProblem => "not a valid controller problem",
            CanErrorDecodingFailure::InvalidViolationType => "not a valid violation type",
            CanErrorDecodingFailure::InvalidLocation => "not a valid location",
            CanErrorDecodingFailure::InvalidTransceiverError => "not a valid transceiver error",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

impl fmt::Display for CanErrorDecodingFailure {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

#[derive(Copy, Clone, Debug)]
pub enum CanError {
    /// TX timeout (by netdevice driver)
    TransmitTimeout,

    /// Arbitration was lost. Contains the number after which arbitration was
    /// lost or 0 if unspecified
    LostArbitration(u8),
    ControllerProblem(ControllerProblem),
    ProtocolViolation {
        vtype: ViolationType,
        location: Location,
    },
    TransceiverError,
    NoAck,
    BusOff,
    BusError,
    Restarted,
    Unknown(u32),
}

#[derive(Copy, Clone, Debug)]
pub enum ControllerProblem {
    // unspecified
    Unspecified,

    // RX buffer overflow
    ReceiveBufferOverflow,

    // TX buffer overflow
    TransmitBufferOverflow,

    // reached warning level for RX errors
    ReceiveErrorWarning,

    // reached warning level for TX errors
    TransmitErrorWarning,

    // reached error passive status RX
    ReceiveErrorPassive,

    // reached error passive status TX
    TransmitErrorPassive,

    // recovered to error active state
    Active,
}

impl TryFrom<u8> for ControllerProblem {
    type Err = CanErrorDecodingFailure;

    fn try_from(val: u8) -> Result<ControllerProblem, CanErrorDecodingFailure> {
        Ok(match val {
            0x00 => ControllerProblem::Unspecified,
            0x01 => ControllerProblem::ReceiveBufferOverflow,
            0x02 => ControllerProblem::TransmitBufferOverflow,
            0x04 => ControllerProblem::ReceiveErrorWarning,
            0x08 => ControllerProblem::TransmitErrorWarning,
            0x10 => ControllerProblem::ReceiveErrorPassive,
            0x20 => ControllerProblem::TransmitErrorPassive,
            0x40 => ControllerProblem::Active,
            _ => return Err(CanErrorDecodingFailure::InvalidControllerProblem),
        })
    }
}

#[derive(Copy, Clone, Debug)]
pub enum ViolationType {
    Unspecified, // unspecified
    SingleBitError, // single bit error
    FrameFormatError, // frame format error
    BitStuffingError, // bit stuffing error
    UnableToSendDominantBit, // unable to send dominant bit
    UnableToSendRecessiveBit, // unable to send recessive bit
    BusOverload, // bus overload
    Active, // active error announcement
    TransmissionError, // error occurred on transmission
}

impl TryFrom<u8> for ViolationType {
    type Err = CanErrorDecodingFailure;

    fn try_from(val: u8) -> Result<ViolationType, CanErrorDecodingFailure> {
        Ok(match val {
            0x00 => ViolationType::Unspecified,
            0x01 => ViolationType::SingleBitError,
            0x02 => ViolationType::FrameFormatError,
            0x04 => ViolationType::BitStuffingError,
            0x08 => ViolationType::UnableToSendDominantBit,
            0x10 => ViolationType::UnableToSendRecessiveBit,
            0x20 => ViolationType::BusOverload,
            0x40 => ViolationType::Active,
            0x80 => ViolationType::TransmissionError,
            _ => return Err(CanErrorDecodingFailure::InvalidViolationType),
        })
    }
}

/// Location
///
/// Describes where inside a received frame an error occured.
#[derive(Copy, Clone, Debug)]
pub enum Location {
    /// Unspecified
    Unspecified,

    /// Start of frame.
    StartOfFrame,

    /// ID bits 28-21 (SFF: 10-3)
    Id2821,

    /// ID bits 20-18 (SFF: 2-0)
    Id2018,

    /// substitute RTR (SFF: RTR)
    SubstituteRtr,

    /// extension of identifier
    IdentifierExtension,

    /// ID bits 17-13
    Id1713,

    /// ID bits 12-5
    Id1205,

    /// ID bits 4-0
    Id0400,

    /// RTR bit
    Rtr,

    /// Reserved bit 1
    Reserved1,

    /// Reserved bit 0
    Reserved0,

    /// Data length
    DataLengthCode,

    /// Data section
    DataSection,

    /// CRC sequence
    CrcSequence,

    /// CRC delimiter
    CrcDelimiter,

    /// ACK slot
    AckSlot,

    /// ACK delimiter
    AckDelimiter,

    /// End-of-frame
    EndOfFrame,

    /// Intermission (between frames)
    Intermission,
}

impl TryFrom<u8> for Location {
    type Err = CanErrorDecodingFailure;

    fn try_from(val: u8) -> Result<Location, CanErrorDecodingFailure> {
        Ok(match val {
            0x00 => Location::Unspecified,
            0x03 => Location::StartOfFrame,
            0x02 => Location::Id2821,
            0x06 => Location::Id2018,
            0x04 => Location::SubstituteRtr,
            0x05 => Location::IdentifierExtension,
            0x07 => Location::Id1713,
            0x0F => Location::Id1205,
            0x0E => Location::Id0400,
            0x0C => Location::Rtr,
            0x0D => Location::Reserved1,
            0x09 => Location::Reserved0,
            0x0B => Location::DataLengthCode,
            0x0A => Location::DataSection,
            0x08 => Location::CrcSequence,
            0x18 => Location::CrcDelimiter,
            0x19 => Location::AckSlot,
            0x1B => Location::AckDelimiter,
            0x1A => Location::EndOfFrame,
            0x12 => Location::Intermission,
            _ => return Err(CanErrorDecodingFailure::InvalidLocation),
        })
    }
}

pub enum TransceiverError {
    Unspecified,
    CanHighNoWire,
    CanHighShortToBat,
    CanHighShortToVcc,
    CanHighShortToGnd,
    CanLowNoWire,
    CanLowShortToBat,
    CanLowShortToVcc,
    CanLowShortToGnd,
    CanLowShortToCanHigh,
}

impl TryFrom<u8> for TransceiverError {
    type Err = CanErrorDecodingFailure;

    fn try_from(val: u8) -> Result<TransceiverError, CanErrorDecodingFailure> {
        Ok(match val {
            0x00 => TransceiverError::Unspecified,
            0x04 => TransceiverError::CanHighNoWire,
            0x05 => TransceiverError::CanHighShortToBat,
            0x06 => TransceiverError::CanHighShortToVcc,
            0x07 => TransceiverError::CanHighShortToGnd,
            0x40 => TransceiverError::CanLowNoWire,
            0x50 => TransceiverError::CanLowShortToBat,
            0x60 => TransceiverError::CanLowShortToVcc,
            0x70 => TransceiverError::CanLowShortToGnd,
            0x80 => TransceiverError::CanLowShortToCanHigh,
            _ => return Err(CanErrorDecodingFailure::InvalidTransceiverError),
        })
    }
}

impl CanError {
    pub fn from_frame(frame: &CanFrame) -> Result<CanError, CanErrorDecodingFailure> {
        if !frame.is_error() {
            return Err(CanErrorDecodingFailure::NotAnError);
        }

        match frame.err() {
            0x00000001 => Ok(CanError::TransmitTimeout),
            0x00000002 => Ok(CanError::LostArbitration(get_data(frame, 0)?)),
            0x00000004 => {
                Ok(CanError::ControllerProblem(ControllerProblem::try_from(get_data(frame, 1)?)?))
            }

            0x00000008 => {
                Ok(CanError::ProtocolViolation {
                    vtype: ViolationType::try_from(get_data(frame, 2)?)?,
                    location: Location::try_from(get_data(frame, 3)?)?,
                })
            }

            0x00000010 => Ok(CanError::TransceiverError),
            0x00000020 => Ok(CanError::NoAck),
            0x00000040 => Ok(CanError::BusOff),
            0x00000080 => Ok(CanError::BusError),
            0x00000100 => Ok(CanError::Restarted),
            e => Err(CanErrorDecodingFailure::UnknownErrorType(e)),
        }
    }
}

pub trait ControllerSpecificErrorInformation {
    fn get_ctrl_err(&self) -> Option<&[u8]>;
}

impl ControllerSpecificErrorInformation for CanFrame {
    #[inline]
    fn get_ctrl_err(&self) -> Option<&[u8]> {
        let data = self.data();

        if data.len() != 8 {
            None
        } else {
            Some(&data[5..])
        }
    }
}
<commit_msg>feat: All errors implemeted std::error::Error.<commit_after>// information from https://raw.githubusercontent.com/torvalds/linux/master/
//                  /include/uapi/linux/can/error.h

use try_from::TryFrom;
use super::CanFrame;
use std::error::Error;
use std::{error, fmt};

#[inline]
/// Helper function to retrieve a specific byte of frame data or returning an
/// `Err(..)` otherwise.
fn get_data(frame: &CanFrame, idx: u8) -> Result<u8, CanErrorDecodingFailure> {
    Ok(*(frame.data().get(idx as usize).ok_or(CanErrorDecodingFailure::NotEnoughData(idx)))?)
}

/// Error decoding a CanError from a CanFrame.
#[derive(Copy, Clone, Debug)]
pub enum CanErrorDecodingFailure {
    /// The supplied CanFrame did not have the error bit set.
    NotAnError,

    /// The error type is not known and cannot be decoded.
    UnknownErrorType(u32),

    /// The error type indicated a need for additional information as `data`,
    /// but the `data` field was not long enough.
    NotEnoughData(u8),

    /// The error type `ControllerProblem` was indicated and additional
    /// information found, but not recognized.
    InvalidControllerProblem,

    /// The type of the ProtocolViolation was not valid
    InvalidViolationType,

    /// A location was specified for a ProtocolViolation, but the location
    /// was not valid.
    InvalidLocation,

    /// The supplied transciever error was invalid.
    InvalidTransceiverError,
}

impl error::Error for CanErrorDecodingFailure {
    fn description(&self) -> &str {
        match *self {
            CanErrorDecodingFailure::NotAnError => "CAN frame is not an error",
            CanErrorDecodingFailure::UnknownErrorType(_) => "unknown error type",
            CanErrorDecodingFailure::NotEnoughData(_) => "not enough data",
            CanErrorDecodingFailure::InvalidControllerProblem => "not a valid controller problem",
            CanErrorDecodingFailure::InvalidViolationType => "not a valid violation type",
            CanErrorDecodingFailure::InvalidLocation => "not a valid location",
            CanErrorDecodingFailure::InvalidTransceiverError => "not a valid transceiver error",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

impl fmt::Display for CanErrorDecodingFailure {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

#[derive(Copy, Clone, Debug)]
pub enum CanError {
    /// TX timeout (by netdevice driver)
    TransmitTimeout,

    /// Arbitration was lost. Contains the number after which arbitration was
    /// lost or 0 if unspecified
    LostArbitration(u8),

    /// Controller problem, see `ControllerProblem`
    ControllerProblem(ControllerProblem),

    /// Protocol violation at the specified `Location`. See `ProtocolViolation`
    /// for details.
    ProtocolViolation {
        vtype: ViolationType,
        location: Location,
    },

    /// Transceiver Error.
    TransceiverError,

    /// No ACK received for current CAN frame.
    NoAck,

    /// Bus off (due to too many detected errors)
    BusOff,

    /// Bus error (due to too many detected errors)
    BusError,

    /// The bus has been restarted
    Restarted,

    /// Unknown, possibly invalid, error
    Unknown(u32),
}

impl error::Error for CanError {
    fn description(&self) -> &str {
        match *self {
            CanError::TransmitTimeout => "transmission timeout",
            CanError::LostArbitration(_) => "arbitration lost",
            CanError::ControllerProblem(_) => "controller problem",
            CanError::ProtocolViolation { .. } => "protocol violation",
            CanError::TransceiverError => "transceiver error",
            CanError::NoAck => "no ack",
            CanError::BusOff => "bus off",
            CanError::BusError => "bus error",
            CanError::Restarted => "restarted",
            CanError::Unknown(_) => "unknown error",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            CanError::ControllerProblem(ref e) => Some(e),
            _ => None,
        }
    }
}

impl fmt::Display for CanError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CanError::LostArbitration(n) => write!(f, "arbitration lost after {} bits", n),
            CanError::ControllerProblem(e) => write!(f, "controller problem: {}", e),
            CanError::ProtocolViolation { vtype, location } => {
                write!(f, "protocol violation at {}: {}", location, vtype)
            }
            CanError::Unknown(errno) => write!(f, "unknown error ({})", errno),
            _ => write!(f, "{}", self.description()),
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub enum ControllerProblem {
    // unspecified
    Unspecified,

    // RX buffer overflow
    ReceiveBufferOverflow,

    // TX buffer overflow
    TransmitBufferOverflow,

    // reached warning level for RX errors
    ReceiveErrorWarning,

    // reached warning level for TX errors
    TransmitErrorWarning,

    // reached error passive status RX
    ReceiveErrorPassive,

    // reached error passive status TX
    TransmitErrorPassive,

    // recovered to error active state
    Active,
}

impl error::Error for ControllerProblem {
    fn description(&self) -> &str {
        match *self {
            ControllerProblem::Unspecified => "unspecified controller problem",
            ControllerProblem::ReceiveBufferOverflow => "receive buffer overflow",
            ControllerProblem::TransmitBufferOverflow => "transmit buffer overflow",
            ControllerProblem::ReceiveErrorWarning => "ERROR WARNING (receive)",
            ControllerProblem::TransmitErrorWarning => "ERROR WARNING (transmit)",
            ControllerProblem::ReceiveErrorPassive => "ERROR PASSIVE (receive)",
            ControllerProblem::TransmitErrorPassive => "ERROR PASSIVE (transmit)",
            ControllerProblem::Active => "ERROR ACTIVE",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

impl fmt::Display for ControllerProblem {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl TryFrom<u8> for ControllerProblem {
    type Err = CanErrorDecodingFailure;

    fn try_from(val: u8) -> Result<ControllerProblem, CanErrorDecodingFailure> {
        Ok(match val {
            0x00 => ControllerProblem::Unspecified,
            0x01 => ControllerProblem::ReceiveBufferOverflow,
            0x02 => ControllerProblem::TransmitBufferOverflow,
            0x04 => ControllerProblem::ReceiveErrorWarning,
            0x08 => ControllerProblem::TransmitErrorWarning,
            0x10 => ControllerProblem::ReceiveErrorPassive,
            0x20 => ControllerProblem::TransmitErrorPassive,
            0x40 => ControllerProblem::Active,
            _ => return Err(CanErrorDecodingFailure::InvalidControllerProblem),
        })
    }
}

#[derive(Copy, Clone, Debug)]
pub enum ViolationType {
    /// Unspecified Violation
    Unspecified,

    /// Single Bit Error
    SingleBitError,

    /// Frame formatting error
    FrameFormatError,

    /// Bit stuffing error
    BitStuffingError,

    /// A dominant bit was sent, but not received
    UnableToSendDominantBit,

    /// A recessive bit was sent, but not received
    UnableToSendRecessiveBit,

    /// Bus overloaded
    BusOverload,

    /// Bus is active (again)
    Active,

    /// Transmission Error
    TransmissionError,
}

impl error::Error for ViolationType {
    fn description(&self) -> &str {
        match *self {
            ViolationType::Unspecified => "unspecified",
            ViolationType::SingleBitError => "single bit error",
            ViolationType::FrameFormatError => "frame format error",
            ViolationType::BitStuffingError => "bit stuffing error",
            ViolationType::UnableToSendDominantBit => "unable to send dominant bit",
            ViolationType::UnableToSendRecessiveBit => "unable to send recessive bit",
            ViolationType::BusOverload => "bus overload",
            ViolationType::Active => "active",
            ViolationType::TransmissionError => "transmission error",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

impl fmt::Display for ViolationType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl TryFrom<u8> for ViolationType {
    type Err = CanErrorDecodingFailure;

    fn try_from(val: u8) -> Result<ViolationType, CanErrorDecodingFailure> {
        Ok(match val {
            0x00 => ViolationType::Unspecified,
            0x01 => ViolationType::SingleBitError,
            0x02 => ViolationType::FrameFormatError,
            0x04 => ViolationType::BitStuffingError,
            0x08 => ViolationType::UnableToSendDominantBit,
            0x10 => ViolationType::UnableToSendRecessiveBit,
            0x20 => ViolationType::BusOverload,
            0x40 => ViolationType::Active,
            0x80 => ViolationType::TransmissionError,
            _ => return Err(CanErrorDecodingFailure::InvalidViolationType),
        })
    }
}

/// Location
///
/// Describes where inside a received frame an error occured.
#[derive(Copy, Clone, Debug)]
pub enum Location {
    /// Unspecified
    Unspecified,

    /// Start of frame.
    StartOfFrame,

    /// ID bits 28-21 (SFF: 10-3)
    Id2821,

    /// ID bits 20-18 (SFF: 2-0)
    Id2018,

    /// substitute RTR (SFF: RTR)
    SubstituteRtr,

    /// extension of identifier
    IdentifierExtension,

    /// ID bits 17-13
    Id1713,

    /// ID bits 12-5
    Id1205,

    /// ID bits 4-0
    Id0400,

    /// RTR bit
    Rtr,

    /// Reserved bit 1
    Reserved1,

    /// Reserved bit 0
    Reserved0,

    /// Data length
    DataLengthCode,

    /// Data section
    DataSection,

    /// CRC sequence
    CrcSequence,

    /// CRC delimiter
    CrcDelimiter,

    /// ACK slot
    AckSlot,

    /// ACK delimiter
    AckDelimiter,

    /// End-of-frame
    EndOfFrame,

    /// Intermission (between frames)
    Intermission,
}

impl fmt::Display for Location {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}",
               match *self {
                   Location::Unspecified => "unspecified location",
                   Location::StartOfFrame => "start of frame",
                   Location::Id2821 => "ID, bits 28-21",
                   Location::Id2018 => "ID, bits 20-18",
                   Location::SubstituteRtr => "substitute RTR bit",
                   Location::IdentifierExtension => "ID, extension",
                   Location::Id1713 => "ID, bits 17-13",
                   Location::Id1205 => "ID, bits 12-05",
                   Location::Id0400 => "ID, bits 04-00",
                   Location::Rtr => "RTR bit",
                   Location::Reserved1 => "reserved bit 1",
                   Location::Reserved0 => "reserved bit 0",
                   Location::DataLengthCode => "data length code",
                   Location::DataSection => "data section",
                   Location::CrcSequence => "CRC sequence",
                   Location::CrcDelimiter => "CRC delimiter",
                   Location::AckSlot => "ACK slot",
                   Location::AckDelimiter => "ACK delimiter",
                   Location::EndOfFrame => "end of frame",
                   Location::Intermission => "intermission",
               })
    }
}
impl TryFrom<u8> for Location {
    type Err = CanErrorDecodingFailure;

    fn try_from(val: u8) -> Result<Location, CanErrorDecodingFailure> {
        Ok(match val {
            0x00 => Location::Unspecified,
            0x03 => Location::StartOfFrame,
            0x02 => Location::Id2821,
            0x06 => Location::Id2018,
            0x04 => Location::SubstituteRtr,
            0x05 => Location::IdentifierExtension,
            0x07 => Location::Id1713,
            0x0F => Location::Id1205,
            0x0E => Location::Id0400,
            0x0C => Location::Rtr,
            0x0D => Location::Reserved1,
            0x09 => Location::Reserved0,
            0x0B => Location::DataLengthCode,
            0x0A => Location::DataSection,
            0x08 => Location::CrcSequence,
            0x18 => Location::CrcDelimiter,
            0x19 => Location::AckSlot,
            0x1B => Location::AckDelimiter,
            0x1A => Location::EndOfFrame,
            0x12 => Location::Intermission,
            _ => return Err(CanErrorDecodingFailure::InvalidLocation),
        })
    }
}

pub enum TransceiverError {
    Unspecified,
    CanHighNoWire,
    CanHighShortToBat,
    CanHighShortToVcc,
    CanHighShortToGnd,
    CanLowNoWire,
    CanLowShortToBat,
    CanLowShortToVcc,
    CanLowShortToGnd,
    CanLowShortToCanHigh,
}

impl TryFrom<u8> for TransceiverError {
    type Err = CanErrorDecodingFailure;

    fn try_from(val: u8) -> Result<TransceiverError, CanErrorDecodingFailure> {
        Ok(match val {
            0x00 => TransceiverError::Unspecified,
            0x04 => TransceiverError::CanHighNoWire,
            0x05 => TransceiverError::CanHighShortToBat,
            0x06 => TransceiverError::CanHighShortToVcc,
            0x07 => TransceiverError::CanHighShortToGnd,
            0x40 => TransceiverError::CanLowNoWire,
            0x50 => TransceiverError::CanLowShortToBat,
            0x60 => TransceiverError::CanLowShortToVcc,
            0x70 => TransceiverError::CanLowShortToGnd,
            0x80 => TransceiverError::CanLowShortToCanHigh,
            _ => return Err(CanErrorDecodingFailure::InvalidTransceiverError),
        })
    }
}

impl CanError {
    pub fn from_frame(frame: &CanFrame) -> Result<CanError, CanErrorDecodingFailure> {
        if !frame.is_error() {
            return Err(CanErrorDecodingFailure::NotAnError);
        }

        match frame.err() {
            0x00000001 => Ok(CanError::TransmitTimeout),
            0x00000002 => Ok(CanError::LostArbitration(get_data(frame, 0)?)),
            0x00000004 => {
                Ok(CanError::ControllerProblem(ControllerProblem::try_from(get_data(frame, 1)?)?))
            }

            0x00000008 => {
                Ok(CanError::ProtocolViolation {
                    vtype: ViolationType::try_from(get_data(frame, 2)?)?,
                    location: Location::try_from(get_data(frame, 3)?)?,
                })
            }

            0x00000010 => Ok(CanError::TransceiverError),
            0x00000020 => Ok(CanError::NoAck),
            0x00000040 => Ok(CanError::BusOff),
            0x00000080 => Ok(CanError::BusError),
            0x00000100 => Ok(CanError::Restarted),
            e => Err(CanErrorDecodingFailure::UnknownErrorType(e)),
        }
    }
}

pub trait ControllerSpecificErrorInformation {
    fn get_ctrl_err(&self) -> Option<&[u8]>;
}

impl ControllerSpecificErrorInformation for CanFrame {
    #[inline]
    fn get_ctrl_err(&self) -> Option<&[u8]> {
        let data = self.data();

        if data.len() != 8 {
            None
        } else {
            Some(&data[5..])
        }
    }
}
<|endoftext|>


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

//! Operations and constants for 32-bits floats (`f32` type)

#![doc(primitive = "f32")]
// FIXME: MIN_VALUE and MAX_VALUE literals are parsed as -inf and inf #14353
#![allow(type_overflow)]

use intrinsics;
use mem;
use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
use num::Float;
use option::Option;

pub static RADIX: uint = 2u;

pub static MANTISSA_DIGITS: uint = 24u;
pub static DIGITS: uint = 6u;

pub static EPSILON: f32 = 1.19209290e-07_f32;

/// Smallest finite f32 value
pub static MIN_VALUE: f32 = -3.40282347e+38_f32;
/// Smallest positive, normalized f32 value
pub static MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
/// Largest finite f32 value
pub static MAX_VALUE: f32 = 3.40282347e+38_f32;

pub static MIN_EXP: int = -125;
pub static MAX_EXP: int = 128;

pub static MIN_10_EXP: int = -37;
pub static MAX_10_EXP: int = 38;

pub static NAN: f32 = 0.0_f32/0.0_f32;
pub static INFINITY: f32 = 1.0_f32/0.0_f32;
pub static NEG_INFINITY: f32 = -1.0_f32/0.0_f32;

/// Various useful constants.
pub mod consts {
    // FIXME: replace with mathematical constants from cmath.

    // FIXME(#5527): These constants should be deprecated once associated
    // constants are implemented in favour of referencing the respective members
    // of `Float`.

    /// Archimedes' constant
    pub static PI: f32 = 3.14159265358979323846264338327950288_f32;

    /// pi * 2.0
    pub static PI_2: f32 = 6.28318530717958647692528676655900576_f32;

    /// pi/2.0
    pub static FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;

    /// pi/3.0
    pub static FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32;

    /// pi/4.0
    pub static FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32;

    /// pi/6.0
    pub static FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32;

    /// pi/8.0
    pub static FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32;

    /// 1.0/pi
    pub static FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;

    /// 2.0/pi
    pub static FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;

    /// 2.0/sqrt(pi)
    pub static FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32;

    /// sqrt(2.0)
    pub static SQRT2: f32 = 1.41421356237309504880168872420969808_f32;

    /// 1.0/sqrt(2.0)
    pub static FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32;

    /// Euler's number
    pub static E: f32 = 2.71828182845904523536028747135266250_f32;

    /// log2(e)
    pub static LOG2_E: f32 = 1.44269504088896340735992468100189214_f32;

    /// log10(e)
    pub static LOG10_E: f32 = 0.434294481903251827651128918916605082_f32;

    /// ln(2.0)
    pub static LN_2: f32 = 0.693147180559945309417232121458176568_f32;

    /// ln(10.0)
    pub static LN_10: f32 = 2.30258509299404568401799145468436421_f32;
}

impl Float for f32 {
    #[inline]
    fn nan() -> f32 { NAN }

    #[inline]
    fn infinity() -> f32 { INFINITY }

    #[inline]
    fn neg_infinity() -> f32 { NEG_INFINITY }

    #[inline]
    fn neg_zero() -> f32 { -0.0 }

    /// Returns `true` if the number is NaN.
    #[inline]
    fn is_nan(self) -> bool { self != self }

    /// Returns `true` if the number is infinite.
    #[inline]
    fn is_infinite(self) -> bool {
        self == Float::infinity() || self == Float::neg_infinity()
    }

    /// Returns `true` if the number is neither infinite or NaN.
    #[inline]
    fn is_finite(self) -> bool {
        !(self.is_nan() || self.is_infinite())
    }

    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
    #[inline]
    fn is_normal(self) -> bool {
        self.classify() == FPNormal
    }

    /// Returns the floating point category of the number. If only one property
    /// is going to be tested, it is generally faster to use the specific
    /// predicate instead.
    fn classify(self) -> FPCategory {
        static EXP_MASK: u32 = 0x7f800000;
        static MAN_MASK: u32 = 0x007fffff;

        let bits: u32 = unsafe { mem::transmute(self) };
        match (bits & MAN_MASK, bits & EXP_MASK) {
            (0, 0)        => FPZero,
            (_, 0)        => FPSubnormal,
            (0, EXP_MASK) => FPInfinite,
            (_, EXP_MASK) => FPNaN,
            _             => FPNormal,
        }
    }

    #[inline]
    fn mantissa_digits(_: Option<f32>) -> uint { MANTISSA_DIGITS }

    #[inline]
    fn digits(_: Option<f32>) -> uint { DIGITS }

    #[inline]
    fn epsilon() -> f32 { EPSILON }

    #[inline]
    fn min_exp(_: Option<f32>) -> int { MIN_EXP }

    #[inline]
    fn max_exp(_: Option<f32>) -> int { MAX_EXP }

    #[inline]
    fn min_10_exp(_: Option<f32>) -> int { MIN_10_EXP }

    #[inline]
    fn max_10_exp(_: Option<f32>) -> int { MAX_10_EXP }

    #[inline]
    fn min_pos_value(_: Option<f32>) -> f32 { MIN_POS_VALUE }

    /// Returns the mantissa, exponent and sign as integers.
    fn integer_decode(self) -> (u64, i16, i8) {
        let bits: u32 = unsafe { mem::transmute(self) };
        let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
        let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
        let mantissa = if exponent == 0 {
            (bits & 0x7fffff) << 1
        } else {
            (bits & 0x7fffff) | 0x800000
        };
        // Exponent bias + mantissa shift
        exponent -= 127 + 23;
        (mantissa as u64, exponent, sign)
    }

    /// Rounds towards minus infinity.
    #[inline]
    fn floor(self) -> f32 {
        unsafe { intrinsics::floorf32(self) }
    }

    /// Rounds towards plus infinity.
    #[inline]
    fn ceil(self) -> f32 {
        unsafe { intrinsics::ceilf32(self) }
    }

    /// Rounds to nearest integer. Rounds half-way cases away from zero.
    #[inline]
    fn round(self) -> f32 {
        unsafe { intrinsics::roundf32(self) }
    }

    /// Returns the integer part of the number (rounds towards zero).
    #[inline]
    fn trunc(self) -> f32 {
        unsafe { intrinsics::truncf32(self) }
    }

    /// The fractional part of the number, satisfying:
    ///
    /// ```rust
    /// let x = 1.65f32;
    /// assert!(x == x.trunc() + x.fract())
    /// ```
    #[inline]
    fn fract(self) -> f32 { self - self.trunc() }

    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
    /// error. This produces a more accurate result with better performance than
    /// a separate multiplication operation followed by an add.
    #[inline]
    fn mul_add(self, a: f32, b: f32) -> f32 {
        unsafe { intrinsics::fmaf32(self, a, b) }
    }

    /// Returns the reciprocal (multiplicative inverse) of the number.
    #[inline]
    fn recip(self) -> f32 { 1.0 / self }

    fn powi(self, n: i32) -> f32 {
        unsafe { intrinsics::powif32(self, n) }
    }

    #[inline]
    fn powf(self, n: f32) -> f32 {
        unsafe { intrinsics::powf32(self, n) }
    }

    /// sqrt(2.0)
    #[inline]
    fn sqrt2() -> f32 { consts::SQRT2 }

    /// 1.0 / sqrt(2.0)
    #[inline]
    fn frac_1_sqrt2() -> f32 { consts::FRAC_1_SQRT2 }

    #[inline]
    fn sqrt(self) -> f32 {
        unsafe { intrinsics::sqrtf32(self) }
    }

    #[inline]
    fn rsqrt(self) -> f32 { self.sqrt().recip() }

    /// Archimedes' constant
    #[inline]
    fn pi() -> f32 { consts::PI }

    /// 2.0 * pi
    #[inline]
    fn two_pi() -> f32 { consts::PI_2 }

    /// pi / 2.0
    #[inline]
    fn frac_pi_2() -> f32 { consts::FRAC_PI_2 }

    /// pi / 3.0
    #[inline]
    fn frac_pi_3() -> f32 { consts::FRAC_PI_3 }

    /// pi / 4.0
    #[inline]
    fn frac_pi_4() -> f32 { consts::FRAC_PI_4 }

    /// pi / 6.0
    #[inline]
    fn frac_pi_6() -> f32 { consts::FRAC_PI_6 }

    /// pi / 8.0
    #[inline]
    fn frac_pi_8() -> f32 { consts::FRAC_PI_8 }

    /// 1 .0/ pi
    #[inline]
    fn frac_1_pi() -> f32 { consts::FRAC_1_PI }

    /// 2.0 / pi
    #[inline]
    fn frac_2_pi() -> f32 { consts::FRAC_2_PI }

    /// 2.0 / sqrt(pi)
    #[inline]
    fn frac_2_sqrtpi() -> f32 { consts::FRAC_2_SQRTPI }

    /// Euler's number
    #[inline]
    fn e() -> f32 { consts::E }

    /// log2(e)
    #[inline]
    fn log2_e() -> f32 { consts::LOG2_E }

    /// log10(e)
    #[inline]
    fn log10_e() -> f32 { consts::LOG10_E }

    /// ln(2.0)
    #[inline]
    fn ln_2() -> f32 { consts::LN_2 }

    /// ln(10.0)
    #[inline]
    fn ln_10() -> f32 { consts::LN_10 }

    /// Returns the exponential of the number.
    #[inline]
    fn exp(self) -> f32 {
        unsafe { intrinsics::expf32(self) }
    }

    /// Returns 2 raised to the power of the number.
    #[inline]
    fn exp2(self) -> f32 {
        unsafe { intrinsics::exp2f32(self) }
    }

    /// Returns the natural logarithm of the number.
    #[inline]
    fn ln(self) -> f32 {
        unsafe { intrinsics::logf32(self) }
    }

    /// Returns the logarithm of the number with respect to an arbitrary base.
    #[inline]
    fn log(self, base: f32) -> f32 { self.ln() / base.ln() }

    /// Returns the base 2 logarithm of the number.
    #[inline]
    fn log2(self) -> f32 {
        unsafe { intrinsics::log2f32(self) }
    }

    /// Returns the base 10 logarithm of the number.
    #[inline]
    fn log10(self) -> f32 {
        unsafe { intrinsics::log10f32(self) }
    }

    /// Converts to degrees, assuming the number is in radians.
    #[inline]
    fn to_degrees(self) -> f32 { self * (180.0f32 / Float::pi()) }

    /// Converts to radians, assuming the number is in degrees.
    #[inline]
    fn to_radians(self) -> f32 {
        let value: f32 = Float::pi();
        self * (value / 180.0f32)
    }
}
<commit_msg>libcore: Fix documentation comment for f32.<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Operations and constants for 32-bits floats (`f32` type)

#![doc(primitive = "f32")]
// FIXME: MIN_VALUE and MAX_VALUE literals are parsed as -inf and inf #14353
#![allow(type_overflow)]

use intrinsics;
use mem;
use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
use num::Float;
use option::Option;

pub static RADIX: uint = 2u;

pub static MANTISSA_DIGITS: uint = 24u;
pub static DIGITS: uint = 6u;

pub static EPSILON: f32 = 1.19209290e-07_f32;

/// Smallest finite f32 value
pub static MIN_VALUE: f32 = -3.40282347e+38_f32;
/// Smallest positive, normalized f32 value
pub static MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
/// Largest finite f32 value
pub static MAX_VALUE: f32 = 3.40282347e+38_f32;

pub static MIN_EXP: int = -125;
pub static MAX_EXP: int = 128;

pub static MIN_10_EXP: int = -37;
pub static MAX_10_EXP: int = 38;

pub static NAN: f32 = 0.0_f32/0.0_f32;
pub static INFINITY: f32 = 1.0_f32/0.0_f32;
pub static NEG_INFINITY: f32 = -1.0_f32/0.0_f32;

/// Various useful constants.
pub mod consts {
    // FIXME: replace with mathematical constants from cmath.

    // FIXME(#5527): These constants should be deprecated once associated
    // constants are implemented in favour of referencing the respective members
    // of `Float`.

    /// Archimedes' constant
    pub static PI: f32 = 3.14159265358979323846264338327950288_f32;

    /// pi * 2.0
    pub static PI_2: f32 = 6.28318530717958647692528676655900576_f32;

    /// pi/2.0
    pub static FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;

    /// pi/3.0
    pub static FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32;

    /// pi/4.0
    pub static FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32;

    /// pi/6.0
    pub static FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32;

    /// pi/8.0
    pub static FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32;

    /// 1.0/pi
    pub static FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;

    /// 2.0/pi
    pub static FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;

    /// 2.0/sqrt(pi)
    pub static FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32;

    /// sqrt(2.0)
    pub static SQRT2: f32 = 1.41421356237309504880168872420969808_f32;

    /// 1.0/sqrt(2.0)
    pub static FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32;

    /// Euler's number
    pub static E: f32 = 2.71828182845904523536028747135266250_f32;

    /// log2(e)
    pub static LOG2_E: f32 = 1.44269504088896340735992468100189214_f32;

    /// log10(e)
    pub static LOG10_E: f32 = 0.434294481903251827651128918916605082_f32;

    /// ln(2.0)
    pub static LN_2: f32 = 0.693147180559945309417232121458176568_f32;

    /// ln(10.0)
    pub static LN_10: f32 = 2.30258509299404568401799145468436421_f32;
}

impl Float for f32 {
    #[inline]
    fn nan() -> f32 { NAN }

    #[inline]
    fn infinity() -> f32 { INFINITY }

    #[inline]
    fn neg_infinity() -> f32 { NEG_INFINITY }

    #[inline]
    fn neg_zero() -> f32 { -0.0 }

    /// Returns `true` if the number is NaN.
    #[inline]
    fn is_nan(self) -> bool { self != self }

    /// Returns `true` if the number is infinite.
    #[inline]
    fn is_infinite(self) -> bool {
        self == Float::infinity() || self == Float::neg_infinity()
    }

    /// Returns `true` if the number is neither infinite or NaN.
    #[inline]
    fn is_finite(self) -> bool {
        !(self.is_nan() || self.is_infinite())
    }

    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
    #[inline]
    fn is_normal(self) -> bool {
        self.classify() == FPNormal
    }

    /// Returns the floating point category of the number. If only one property
    /// is going to be tested, it is generally faster to use the specific
    /// predicate instead.
    fn classify(self) -> FPCategory {
        static EXP_MASK: u32 = 0x7f800000;
        static MAN_MASK: u32 = 0x007fffff;

        let bits: u32 = unsafe { mem::transmute(self) };
        match (bits & MAN_MASK, bits & EXP_MASK) {
            (0, 0)        => FPZero,
            (_, 0)        => FPSubnormal,
            (0, EXP_MASK) => FPInfinite,
            (_, EXP_MASK) => FPNaN,
            _             => FPNormal,
        }
    }

    #[inline]
    fn mantissa_digits(_: Option<f32>) -> uint { MANTISSA_DIGITS }

    #[inline]
    fn digits(_: Option<f32>) -> uint { DIGITS }

    #[inline]
    fn epsilon() -> f32 { EPSILON }

    #[inline]
    fn min_exp(_: Option<f32>) -> int { MIN_EXP }

    #[inline]
    fn max_exp(_: Option<f32>) -> int { MAX_EXP }

    #[inline]
    fn min_10_exp(_: Option<f32>) -> int { MIN_10_EXP }

    #[inline]
    fn max_10_exp(_: Option<f32>) -> int { MAX_10_EXP }

    #[inline]
    fn min_pos_value(_: Option<f32>) -> f32 { MIN_POS_VALUE }

    /// Returns the mantissa, exponent and sign as integers.
    fn integer_decode(self) -> (u64, i16, i8) {
        let bits: u32 = unsafe { mem::transmute(self) };
        let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
        let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
        let mantissa = if exponent == 0 {
            (bits & 0x7fffff) << 1
        } else {
            (bits & 0x7fffff) | 0x800000
        };
        // Exponent bias + mantissa shift
        exponent -= 127 + 23;
        (mantissa as u64, exponent, sign)
    }

    /// Rounds towards minus infinity.
    #[inline]
    fn floor(self) -> f32 {
        unsafe { intrinsics::floorf32(self) }
    }

    /// Rounds towards plus infinity.
    #[inline]
    fn ceil(self) -> f32 {
        unsafe { intrinsics::ceilf32(self) }
    }

    /// Rounds to nearest integer. Rounds half-way cases away from zero.
    #[inline]
    fn round(self) -> f32 {
        unsafe { intrinsics::roundf32(self) }
    }

    /// Returns the integer part of the number (rounds towards zero).
    #[inline]
    fn trunc(self) -> f32 {
        unsafe { intrinsics::truncf32(self) }
    }

    /// The fractional part of the number, satisfying:
    ///
    /// ```rust
    /// let x = 1.65f32;
    /// assert!(x == x.trunc() + x.fract())
    /// ```
    #[inline]
    fn fract(self) -> f32 { self - self.trunc() }

    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
    /// error. This produces a more accurate result with better performance than
    /// a separate multiplication operation followed by an add.
    #[inline]
    fn mul_add(self, a: f32, b: f32) -> f32 {
        unsafe { intrinsics::fmaf32(self, a, b) }
    }

    /// Returns the reciprocal (multiplicative inverse) of the number.
    #[inline]
    fn recip(self) -> f32 { 1.0 / self }

    fn powi(self, n: i32) -> f32 {
        unsafe { intrinsics::powif32(self, n) }
    }

    #[inline]
    fn powf(self, n: f32) -> f32 {
        unsafe { intrinsics::powf32(self, n) }
    }

    /// sqrt(2.0)
    #[inline]
    fn sqrt2() -> f32 { consts::SQRT2 }

    /// 1.0 / sqrt(2.0)
    #[inline]
    fn frac_1_sqrt2() -> f32 { consts::FRAC_1_SQRT2 }

    #[inline]
    fn sqrt(self) -> f32 {
        unsafe { intrinsics::sqrtf32(self) }
    }

    #[inline]
    fn rsqrt(self) -> f32 { self.sqrt().recip() }

    /// Archimedes' constant
    #[inline]
    fn pi() -> f32 { consts::PI }

    /// 2.0 * pi
    #[inline]
    fn two_pi() -> f32 { consts::PI_2 }

    /// pi / 2.0
    #[inline]
    fn frac_pi_2() -> f32 { consts::FRAC_PI_2 }

    /// pi / 3.0
    #[inline]
    fn frac_pi_3() -> f32 { consts::FRAC_PI_3 }

    /// pi / 4.0
    #[inline]
    fn frac_pi_4() -> f32 { consts::FRAC_PI_4 }

    /// pi / 6.0
    #[inline]
    fn frac_pi_6() -> f32 { consts::FRAC_PI_6 }

    /// pi / 8.0
    #[inline]
    fn frac_pi_8() -> f32 { consts::FRAC_PI_8 }

    /// 1.0 / pi
    #[inline]
    fn frac_1_pi() -> f32 { consts::FRAC_1_PI }

    /// 2.0 / pi
    #[inline]
    fn frac_2_pi() -> f32 { consts::FRAC_2_PI }

    /// 2.0 / sqrt(pi)
    #[inline]
    fn frac_2_sqrtpi() -> f32 { consts::FRAC_2_SQRTPI }

    /// Euler's number
    #[inline]
    fn e() -> f32 { consts::E }

    /// log2(e)
    #[inline]
    fn log2_e() -> f32 { consts::LOG2_E }

    /// log10(e)
    #[inline]
    fn log10_e() -> f32 { consts::LOG10_E }

    /// ln(2.0)
    #[inline]
    fn ln_2() -> f32 { consts::LN_2 }

    /// ln(10.0)
    #[inline]
    fn ln_10() -> f32 { consts::LN_10 }

    /// Returns the exponential of the number.
    #[inline]
    fn exp(self) -> f32 {
        unsafe { intrinsics::expf32(self) }
    }

    /// Returns 2 raised to the power of the number.
    #[inline]
    fn exp2(self) -> f32 {
        unsafe { intrinsics::exp2f32(self) }
    }

    /// Returns the natural logarithm of the number.
    #[inline]
    fn ln(self) -> f32 {
        unsafe { intrinsics::logf32(self) }
    }

    /// Returns the logarithm of the number with respect to an arbitrary base.
    #[inline]
    fn log(self, base: f32) -> f32 { self.ln() / base.ln() }

    /// Returns the base 2 logarithm of the number.
    #[inline]
    fn log2(self) -> f32 {
        unsafe { intrinsics::log2f32(self) }
    }

    /// Returns the base 10 logarithm of the number.
    #[inline]
    fn log10(self) -> f32 {
        unsafe { intrinsics::log10f32(self) }
    }

    /// Converts to degrees, assuming the number is in radians.
    #[inline]
    fn to_degrees(self) -> f32 { self * (180.0f32 / Float::pi()) }

    /// Converts to radians, assuming the number is in degrees.
    #[inline]
    fn to_radians(self) -> f32 {
        let value: f32 = Float::pi();
        self * (value / 180.0f32)
    }
}
<|endoftext|>