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

use std::borrow::Cow;
use std::marker::PhantomData;
use std::mem;
use std::ops::Range;
use std::ptr;
use std::sync::Arc;
use std::ffi::CStr;
use std::vec::IntoIter as VecIntoIter;

use format::Format;
use pipeline::input_assembly::PrimitiveTopology;

use device::Device;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// Contains SPIR-V code with one or more entry points.
///
/// Note that it is advised to wrap around a `ShaderModule` with a struct that is different for
/// each shader.
pub struct ShaderModule {
    device: Arc<Device>,
    module: vk::ShaderModule,
}

impl ShaderModule {
    /// Builds a new shader module from SPIR-V.
    ///
    /// # Safety
    ///
    /// - The SPIR-V code is not validated.
    /// - The SPIR-V code may require some features that are not enabled. This isn't checked by
    ///   this function either.
    ///
    pub unsafe fn new(device: &Arc<Device>, spirv: &[u8])
                      -> Result<Arc<ShaderModule>, OomError>
    {
        let vk = device.pointers();

        assert!((spirv.len() % 4) == 0);

        let module = {
            let infos = vk::ShaderModuleCreateInfo {
                sType: vk::STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                codeSize: spirv.len(),
                pCode: spirv.as_ptr() as *const _,
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateShaderModule(device.internal_object(), &infos,
                                                    ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(ShaderModule {
            device: device.clone(),
            module: module,
        }))
    }

    pub unsafe fn vertex_shader_entry_point<'a, S, I, O, L>
        (&'a self, name: &'a CStr, input: I, output: O, layout: L)
        -> VertexShaderEntryPoint<'a, S, I, O, L>
    {
        VertexShaderEntryPoint {
            module: self,
            name: name,
            input: input,
            output: output,
            layout: layout,
            marker: PhantomData,
        }
    }

    pub unsafe fn tess_control_shader_entry_point<'a, S, I, O, L>
        (&'a self, name: &'a CStr, input: I, output: O, layout: L) -> TessControlShaderEntryPoint<'a, S, I, O, L>
    {
        TessControlShaderEntryPoint {
            module: self,
            name: name,
            layout: layout,
            input: input,
            output: output,
            marker: PhantomData,
        }
    }

    pub unsafe fn tess_evaluation_shader_entry_point<'a, S, I, O, L>
        (&'a self, name: &'a CStr, input: I, output: O, layout: L) -> TessEvaluationShaderEntryPoint<'a, S, I, O, L>
    {
        TessEvaluationShaderEntryPoint {
            module: self,
            name: name,
            layout: layout,
            input: input,
            output: output,
            marker: PhantomData,
        }
    }

    pub unsafe fn geometry_shader_entry_point<'a, S, I, O, L>
        (&'a self, name: &'a CStr, primitives: GeometryShaderExecutionMode, input: I, output: O, layout: L)
        -> GeometryShaderEntryPoint<'a, S, I, O, L>
    {
        GeometryShaderEntryPoint {
            module: self,
            name: name,
            layout: layout,
            primitives: primitives,
            input: input,
            output: output,
            marker: PhantomData,
        }
    }

    /// Gets access to an entry point contained in this module.
    ///
    /// This is purely a *logical* operation. It returns a struct that *represents* the entry
    /// point but doesn't actually do anything.
    ///
    /// # Safety
    ///
    /// - The user must check that the entry point exists in the module, as this is not checked
    ///   by Vulkan.
    /// - Calling this function also determines the template parameters associated to the
    ///   `EntryPoint` struct. Therefore care must be taken that the values there are correct.
    ///
    pub unsafe fn fragment_shader_entry_point<'a, S, I, O, L>(&'a self, name: &'a CStr, input: I, output: O, layout: L)
                                                              -> FragmentShaderEntryPoint<'a, S, I, O, L>
    {
        FragmentShaderEntryPoint {
            module: self,
            name: name,
            layout: layout,
            input: input,
            output: output,
            marker: PhantomData,
        }
    }

    #[inline]
    pub unsafe fn compute_shader_entry_point<'a, S, L>(&'a self, name: &'a CStr, layout: L)
                                                       -> ComputeShaderEntryPoint<'a, S, L>
    {
        ComputeShaderEntryPoint {
            module: self,
            name: name,
            layout: layout,
            marker: PhantomData,
        }
    }
}

unsafe impl VulkanObject for ShaderModule {
    type Object = vk::ShaderModule;

    #[inline]
    fn internal_object(&self) -> vk::ShaderModule {
        self.module
    }
}

impl Drop for ShaderModule {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyShaderModule(self.device.internal_object(), self.module, ptr::null());
        }
    }
}

pub struct VertexShaderEntryPoint<'a, S, I, O, L> {
    module: &'a ShaderModule,
    name: &'a CStr,
    input: I,
    layout: L,
    output: O,
    marker: PhantomData<S>,
}

impl<'a, S, I, O, L> VertexShaderEntryPoint<'a, S, I, O, L> {
    #[inline]
    pub fn module(&self) -> &'a ShaderModule {
        self.module
    }

    #[inline]
    pub fn name(&self) -> &'a CStr {
        self.name
    }

    #[inline]
    pub fn layout(&self) -> &L {
        &self.layout
    }

    // TODO: rename "input" for consistency
    #[inline]
    pub fn input_definition(&self) -> &I {
        &self.input
    }

    #[inline]
    pub fn output(&self) -> &O {
        &self.output
    }
}

pub struct TessControlShaderEntryPoint<'a, S, I, O, L> {
    module: &'a ShaderModule,
    name: &'a CStr,
    layout: L,
    input: I,
    output: O,
    marker: PhantomData<S>,
}

impl<'a, S, I, O, L> TessControlShaderEntryPoint<'a, S, I, O, L> {
    #[inline]
    pub fn module(&self) -> &'a ShaderModule {
        self.module
    }

    #[inline]
    pub fn name(&self) -> &'a CStr {
        self.name
    }

    #[inline]
    pub fn layout(&self) -> &L {
        &self.layout
    }

    #[inline]
    pub fn input(&self) -> &I {
        &self.input
    }

    #[inline]
    pub fn output(&self) -> &O {
        &self.output
    }
}

pub struct TessEvaluationShaderEntryPoint<'a, S, I, O, L> {
    module: &'a ShaderModule,
    name: &'a CStr,
    layout: L,
    input: I,
    output: O,
    marker: PhantomData<S>,
}

impl<'a, S, I, O, L> TessEvaluationShaderEntryPoint<'a, S, I, O, L> {
    #[inline]
    pub fn module(&self) -> &'a ShaderModule {
        self.module
    }

    #[inline]
    pub fn name(&self) -> &'a CStr {
        self.name
    }

    #[inline]
    pub fn layout(&self) -> &L {
        &self.layout
    }

    #[inline]
    pub fn input(&self) -> &I {
        &self.input
    }

    #[inline]
    pub fn output(&self) -> &O {
        &self.output
    }
}

pub struct GeometryShaderEntryPoint<'a, S, I, O, L> {
    module: &'a ShaderModule,
    name: &'a CStr,
    layout: L,
    primitives: GeometryShaderExecutionMode,
    input: I,
    output: O,
    marker: PhantomData<S>,
}

impl<'a, S, I, O, L> GeometryShaderEntryPoint<'a, S, I, O, L> {
    #[inline]
    pub fn module(&self) -> &'a ShaderModule {
        self.module
    }

    #[inline]
    pub fn name(&self) -> &'a CStr {
        self.name
    }

    /// Returns the kind of primitives expected by the geometry shader.
    #[inline]
    pub fn primitives(&self) -> GeometryShaderExecutionMode {
        self.primitives
    }

    #[inline]
    pub fn layout(&self) -> &L {
        &self.layout
    }

    #[inline]
    pub fn input(&self) -> &I {
        &self.input
    }

    #[inline]
    pub fn output(&self) -> &O {
        &self.output
    }
}

/// Declares which type of primitives are expected by the geometry shader.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum GeometryShaderExecutionMode {
    Points,
    Lines,
    LinesWithAdjacency,
    Triangles,
    TrianglesWithAdjacency,
}

impl GeometryShaderExecutionMode {
    /// Returns true if the given primitive topology can be used with this execution mode.
    #[inline]
    pub fn matches(&self, input: PrimitiveTopology) -> bool {
        match (*self, input) {
            (GeometryShaderExecutionMode::Points, PrimitiveTopology::PointList) => true,
            (GeometryShaderExecutionMode::Lines, PrimitiveTopology::LineList) => true,
            (GeometryShaderExecutionMode::Lines, PrimitiveTopology::LineStrip) => true,
            (GeometryShaderExecutionMode::LinesWithAdjacency,
             PrimitiveTopology::LineListWithAdjacency) => true,
            (GeometryShaderExecutionMode::LinesWithAdjacency,
             PrimitiveTopology::LineStripWithAdjacency) => true,
            (GeometryShaderExecutionMode::Triangles, PrimitiveTopology::TriangleList) => true,
            (GeometryShaderExecutionMode::Triangles, PrimitiveTopology::TriangleStrip) => true,
            (GeometryShaderExecutionMode::Triangles, PrimitiveTopology::TriangleFan) => true,
            (GeometryShaderExecutionMode::TrianglesWithAdjacency,
             PrimitiveTopology::TriangleListWithAdjancecy) => true,
            (GeometryShaderExecutionMode::TrianglesWithAdjacency,
             PrimitiveTopology::TriangleStripWithAdjacency) => true,
            _ => false,
        }
    }
}

pub struct FragmentShaderEntryPoint<'a, S, I, O, L> {
    module: &'a ShaderModule,
    name: &'a CStr,
    layout: L,
    input: I,
    output: O,
    marker: PhantomData<S>,
}

impl<'a, S, I, O, L> FragmentShaderEntryPoint<'a, S, I, O, L> {
    #[inline]
    pub fn module(&self) -> &'a ShaderModule {
        self.module
    }

    #[inline]
    pub fn name(&self) -> &'a CStr {
        self.name
    }

    #[inline]
    pub fn layout(&self) -> &L {
        &self.layout
    }

    #[inline]
    pub fn input(&self) -> &I {
        &self.input
    }

    #[inline]
    pub fn output(&self) -> &O {
        &self.output
    }
}

pub struct ComputeShaderEntryPoint<'a, S, L> {
    module: &'a ShaderModule,
    name: &'a CStr,
    layout: L,
    marker: PhantomData<S>,
}

impl<'a, S, L> ComputeShaderEntryPoint<'a, S, L> {
    #[inline]
    pub fn module(&self) -> &'a ShaderModule {
        self.module
    }

    #[inline]
    pub fn name(&self) -> &'a CStr {
        self.name
    }

    #[inline]
    pub fn layout(&self) -> &L {
        &self.layout
    }
}

/// Structs that contain the definition of an interface between two shader stages, or between
/// the outside and a shader stage.
///
/// # Safety
///
/// - Must only provide one entry per location.
/// - The format must not be larger than 128 bits.
///
pub unsafe trait ShaderInterfaceDef {
    /// Iterator returned by `elements`.
    type Iter: ExactSizeIterator<Item = ShaderInterfaceDefEntry>;

    /// Iterates over the elements of the interface.
    fn elements(&self) -> Self::Iter;
}

// FIXME: temporary ; remove as it is unsafe
unsafe impl ShaderInterfaceDef for Vec<ShaderInterfaceDefEntry> {
    type Iter = VecIntoIter<ShaderInterfaceDefEntry>;

    #[inline]
    fn elements(&self) -> Self::Iter {
        self.clone().into_iter()
    }
}

/// Entry of a shader interface definition.
#[derive(Debug, Clone)]
pub struct ShaderInterfaceDefEntry {
    /// Range of locations covered by the element.
    pub location: Range<u32>,
    /// Format of a each location of the element.
    pub format: Format,
    /// Name of the element, or `None` if the name is unknown.
    pub name: Option<Cow<'static, str>>,
}

/// Extension trait for `ShaderInterfaceDef` that specifies that the interface is potentially
/// compatible with another one.
pub unsafe trait ShaderInterfaceDefMatch<I>: ShaderInterfaceDef where I: ShaderInterfaceDef {
    /// Returns true if the two definitions match.
    // TODO: return a descriptive error instead
    fn matches(&self, other: &I) -> bool;
}

// TODO: turn this into a default impl that can be specialized
unsafe impl<T, I> ShaderInterfaceDefMatch<I> for T
    where T: ShaderInterfaceDef, I: ShaderInterfaceDef
{
    fn matches(&self, other: &I) -> bool {
        if self.elements().len() != other.elements().len() {
            return false;
        }

        for a in self.elements() {
            for loc in a.location.clone() {
                let b = match other.elements().find(|e| loc >= e.location.start && loc < e.location.end) {
                    None => return false,
                    Some(b) => b,
                };

                if a.format != b.format {
                    return false;
                }

                // TODO: enforce this?
                /*match (a.name, b.name) {
                    (Some(ref an), Some(ref bn)) => if an != bn { return false },
                    _ => ()
                };*/
            }
        }

        true
    }
}

/// Trait to describe structs that contain specialization data for shaders.
///
/// It is implemented on `()` for shaders that don't have any specialization constant.
pub unsafe trait SpecializationConstants {
    /// Returns descriptors of the struct's layout.
    fn descriptors() -> &'static [SpecializationMapEntry];
}

unsafe impl SpecializationConstants for () {
    #[inline]
    fn descriptors() -> &'static [SpecializationMapEntry] {
        &[]
    }
}

/// Describes an indiviual constant to set in the shader. Also a field in the struct.
// Has the same memory representation as a `VkSpecializationMapEntry`.
#[repr(C)]
pub struct SpecializationMapEntry {
    /// Identifier of the constant in the shader that corresponds to this field.
    pub constant_id: u32,
    /// Offset within this struct for the data.
    pub offset: u32,
    /// Size of the data in bytes.
    pub size: usize,
}
<commit_msg>Remove unsafe code<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::borrow::Cow;
use std::marker::PhantomData;
use std::mem;
use std::ops::Range;
use std::ptr;
use std::sync::Arc;
use std::ffi::CStr;
use std::vec::IntoIter as VecIntoIter;

use format::Format;
use pipeline::input_assembly::PrimitiveTopology;

use device::Device;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// Contains SPIR-V code with one or more entry points.
///
/// Note that it is advised to wrap around a `ShaderModule` with a struct that is different for
/// each shader.
pub struct ShaderModule {
    device: Arc<Device>,
    module: vk::ShaderModule,
}

impl ShaderModule {
    /// Builds a new shader module from SPIR-V.
    ///
    /// # Safety
    ///
    /// - The SPIR-V code is not validated.
    /// - The SPIR-V code may require some features that are not enabled. This isn't checked by
    ///   this function either.
    ///
    pub unsafe fn new(device: &Arc<Device>, spirv: &[u8])
                      -> Result<Arc<ShaderModule>, OomError>
    {
        let vk = device.pointers();

        assert!((spirv.len() % 4) == 0);

        let module = {
            let infos = vk::ShaderModuleCreateInfo {
                sType: vk::STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                codeSize: spirv.len(),
                pCode: spirv.as_ptr() as *const _,
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateShaderModule(device.internal_object(), &infos,
                                                    ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(ShaderModule {
            device: device.clone(),
            module: module,
        }))
    }

    pub unsafe fn vertex_shader_entry_point<'a, S, I, O, L>
        (&'a self, name: &'a CStr, input: I, output: O, layout: L)
        -> VertexShaderEntryPoint<'a, S, I, O, L>
    {
        VertexShaderEntryPoint {
            module: self,
            name: name,
            input: input,
            output: output,
            layout: layout,
            marker: PhantomData,
        }
    }

    pub unsafe fn tess_control_shader_entry_point<'a, S, I, O, L>
        (&'a self, name: &'a CStr, input: I, output: O, layout: L) -> TessControlShaderEntryPoint<'a, S, I, O, L>
    {
        TessControlShaderEntryPoint {
            module: self,
            name: name,
            layout: layout,
            input: input,
            output: output,
            marker: PhantomData,
        }
    }

    pub unsafe fn tess_evaluation_shader_entry_point<'a, S, I, O, L>
        (&'a self, name: &'a CStr, input: I, output: O, layout: L) -> TessEvaluationShaderEntryPoint<'a, S, I, O, L>
    {
        TessEvaluationShaderEntryPoint {
            module: self,
            name: name,
            layout: layout,
            input: input,
            output: output,
            marker: PhantomData,
        }
    }

    pub unsafe fn geometry_shader_entry_point<'a, S, I, O, L>
        (&'a self, name: &'a CStr, primitives: GeometryShaderExecutionMode, input: I, output: O, layout: L)
        -> GeometryShaderEntryPoint<'a, S, I, O, L>
    {
        GeometryShaderEntryPoint {
            module: self,
            name: name,
            layout: layout,
            primitives: primitives,
            input: input,
            output: output,
            marker: PhantomData,
        }
    }

    /// Gets access to an entry point contained in this module.
    ///
    /// This is purely a *logical* operation. It returns a struct that *represents* the entry
    /// point but doesn't actually do anything.
    ///
    /// # Safety
    ///
    /// - The user must check that the entry point exists in the module, as this is not checked
    ///   by Vulkan.
    /// - Calling this function also determines the template parameters associated to the
    ///   `EntryPoint` struct. Therefore care must be taken that the values there are correct.
    ///
    pub unsafe fn fragment_shader_entry_point<'a, S, I, O, L>(&'a self, name: &'a CStr, input: I, output: O, layout: L)
                                                              -> FragmentShaderEntryPoint<'a, S, I, O, L>
    {
        FragmentShaderEntryPoint {
            module: self,
            name: name,
            layout: layout,
            input: input,
            output: output,
            marker: PhantomData,
        }
    }

    #[inline]
    pub unsafe fn compute_shader_entry_point<'a, S, L>(&'a self, name: &'a CStr, layout: L)
                                                       -> ComputeShaderEntryPoint<'a, S, L>
    {
        ComputeShaderEntryPoint {
            module: self,
            name: name,
            layout: layout,
            marker: PhantomData,
        }
    }
}

unsafe impl VulkanObject for ShaderModule {
    type Object = vk::ShaderModule;

    #[inline]
    fn internal_object(&self) -> vk::ShaderModule {
        self.module
    }
}

impl Drop for ShaderModule {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyShaderModule(self.device.internal_object(), self.module, ptr::null());
        }
    }
}

pub struct VertexShaderEntryPoint<'a, S, I, O, L> {
    module: &'a ShaderModule,
    name: &'a CStr,
    input: I,
    layout: L,
    output: O,
    marker: PhantomData<S>,
}

impl<'a, S, I, O, L> VertexShaderEntryPoint<'a, S, I, O, L> {
    #[inline]
    pub fn module(&self) -> &'a ShaderModule {
        self.module
    }

    #[inline]
    pub fn name(&self) -> &'a CStr {
        self.name
    }

    #[inline]
    pub fn layout(&self) -> &L {
        &self.layout
    }

    // TODO: rename "input" for consistency
    #[inline]
    pub fn input_definition(&self) -> &I {
        &self.input
    }

    #[inline]
    pub fn output(&self) -> &O {
        &self.output
    }
}

pub struct TessControlShaderEntryPoint<'a, S, I, O, L> {
    module: &'a ShaderModule,
    name: &'a CStr,
    layout: L,
    input: I,
    output: O,
    marker: PhantomData<S>,
}

impl<'a, S, I, O, L> TessControlShaderEntryPoint<'a, S, I, O, L> {
    #[inline]
    pub fn module(&self) -> &'a ShaderModule {
        self.module
    }

    #[inline]
    pub fn name(&self) -> &'a CStr {
        self.name
    }

    #[inline]
    pub fn layout(&self) -> &L {
        &self.layout
    }

    #[inline]
    pub fn input(&self) -> &I {
        &self.input
    }

    #[inline]
    pub fn output(&self) -> &O {
        &self.output
    }
}

pub struct TessEvaluationShaderEntryPoint<'a, S, I, O, L> {
    module: &'a ShaderModule,
    name: &'a CStr,
    layout: L,
    input: I,
    output: O,
    marker: PhantomData<S>,
}

impl<'a, S, I, O, L> TessEvaluationShaderEntryPoint<'a, S, I, O, L> {
    #[inline]
    pub fn module(&self) -> &'a ShaderModule {
        self.module
    }

    #[inline]
    pub fn name(&self) -> &'a CStr {
        self.name
    }

    #[inline]
    pub fn layout(&self) -> &L {
        &self.layout
    }

    #[inline]
    pub fn input(&self) -> &I {
        &self.input
    }

    #[inline]
    pub fn output(&self) -> &O {
        &self.output
    }
}

pub struct GeometryShaderEntryPoint<'a, S, I, O, L> {
    module: &'a ShaderModule,
    name: &'a CStr,
    layout: L,
    primitives: GeometryShaderExecutionMode,
    input: I,
    output: O,
    marker: PhantomData<S>,
}

impl<'a, S, I, O, L> GeometryShaderEntryPoint<'a, S, I, O, L> {
    #[inline]
    pub fn module(&self) -> &'a ShaderModule {
        self.module
    }

    #[inline]
    pub fn name(&self) -> &'a CStr {
        self.name
    }

    /// Returns the kind of primitives expected by the geometry shader.
    #[inline]
    pub fn primitives(&self) -> GeometryShaderExecutionMode {
        self.primitives
    }

    #[inline]
    pub fn layout(&self) -> &L {
        &self.layout
    }

    #[inline]
    pub fn input(&self) -> &I {
        &self.input
    }

    #[inline]
    pub fn output(&self) -> &O {
        &self.output
    }
}

/// Declares which type of primitives are expected by the geometry shader.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum GeometryShaderExecutionMode {
    Points,
    Lines,
    LinesWithAdjacency,
    Triangles,
    TrianglesWithAdjacency,
}

impl GeometryShaderExecutionMode {
    /// Returns true if the given primitive topology can be used with this execution mode.
    #[inline]
    pub fn matches(&self, input: PrimitiveTopology) -> bool {
        match (*self, input) {
            (GeometryShaderExecutionMode::Points, PrimitiveTopology::PointList) => true,
            (GeometryShaderExecutionMode::Lines, PrimitiveTopology::LineList) => true,
            (GeometryShaderExecutionMode::Lines, PrimitiveTopology::LineStrip) => true,
            (GeometryShaderExecutionMode::LinesWithAdjacency,
             PrimitiveTopology::LineListWithAdjacency) => true,
            (GeometryShaderExecutionMode::LinesWithAdjacency,
             PrimitiveTopology::LineStripWithAdjacency) => true,
            (GeometryShaderExecutionMode::Triangles, PrimitiveTopology::TriangleList) => true,
            (GeometryShaderExecutionMode::Triangles, PrimitiveTopology::TriangleStrip) => true,
            (GeometryShaderExecutionMode::Triangles, PrimitiveTopology::TriangleFan) => true,
            (GeometryShaderExecutionMode::TrianglesWithAdjacency,
             PrimitiveTopology::TriangleListWithAdjancecy) => true,
            (GeometryShaderExecutionMode::TrianglesWithAdjacency,
             PrimitiveTopology::TriangleStripWithAdjacency) => true,
            _ => false,
        }
    }
}

pub struct FragmentShaderEntryPoint<'a, S, I, O, L> {
    module: &'a ShaderModule,
    name: &'a CStr,
    layout: L,
    input: I,
    output: O,
    marker: PhantomData<S>,
}

impl<'a, S, I, O, L> FragmentShaderEntryPoint<'a, S, I, O, L> {
    #[inline]
    pub fn module(&self) -> &'a ShaderModule {
        self.module
    }

    #[inline]
    pub fn name(&self) -> &'a CStr {
        self.name
    }

    #[inline]
    pub fn layout(&self) -> &L {
        &self.layout
    }

    #[inline]
    pub fn input(&self) -> &I {
        &self.input
    }

    #[inline]
    pub fn output(&self) -> &O {
        &self.output
    }
}

pub struct ComputeShaderEntryPoint<'a, S, L> {
    module: &'a ShaderModule,
    name: &'a CStr,
    layout: L,
    marker: PhantomData<S>,
}

impl<'a, S, L> ComputeShaderEntryPoint<'a, S, L> {
    #[inline]
    pub fn module(&self) -> &'a ShaderModule {
        self.module
    }

    #[inline]
    pub fn name(&self) -> &'a CStr {
        self.name
    }

    #[inline]
    pub fn layout(&self) -> &L {
        &self.layout
    }
}

/// Structs that contain the definition of an interface between two shader stages, or between
/// the outside and a shader stage.
///
/// # Safety
///
/// - Must only provide one entry per location.
/// - The format must not be larger than 128 bits.
///
pub unsafe trait ShaderInterfaceDef {
    /// Iterator returned by `elements`.
    type Iter: ExactSizeIterator<Item = ShaderInterfaceDefEntry>;

    /// Iterates over the elements of the interface.
    fn elements(&self) -> Self::Iter;
}

/// Entry of a shader interface definition.
#[derive(Debug, Clone)]
pub struct ShaderInterfaceDefEntry {
    /// Range of locations covered by the element.
    pub location: Range<u32>,
    /// Format of a each location of the element.
    pub format: Format,
    /// Name of the element, or `None` if the name is unknown.
    pub name: Option<Cow<'static, str>>,
}

/// Extension trait for `ShaderInterfaceDef` that specifies that the interface is potentially
/// compatible with another one.
pub unsafe trait ShaderInterfaceDefMatch<I>: ShaderInterfaceDef where I: ShaderInterfaceDef {
    /// Returns true if the two definitions match.
    // TODO: return a descriptive error instead
    fn matches(&self, other: &I) -> bool;
}

// TODO: turn this into a default impl that can be specialized
unsafe impl<T, I> ShaderInterfaceDefMatch<I> for T
    where T: ShaderInterfaceDef, I: ShaderInterfaceDef
{
    fn matches(&self, other: &I) -> bool {
        if self.elements().len() != other.elements().len() {
            return false;
        }

        for a in self.elements() {
            for loc in a.location.clone() {
                let b = match other.elements().find(|e| loc >= e.location.start && loc < e.location.end) {
                    None => return false,
                    Some(b) => b,
                };

                if a.format != b.format {
                    return false;
                }

                // TODO: enforce this?
                /*match (a.name, b.name) {
                    (Some(ref an), Some(ref bn)) => if an != bn { return false },
                    _ => ()
                };*/
            }
        }

        true
    }
}

/// Trait to describe structs that contain specialization data for shaders.
///
/// It is implemented on `()` for shaders that don't have any specialization constant.
pub unsafe trait SpecializationConstants {
    /// Returns descriptors of the struct's layout.
    fn descriptors() -> &'static [SpecializationMapEntry];
}

unsafe impl SpecializationConstants for () {
    #[inline]
    fn descriptors() -> &'static [SpecializationMapEntry] {
        &[]
    }
}

/// Describes an indiviual constant to set in the shader. Also a field in the struct.
// Has the same memory representation as a `VkSpecializationMapEntry`.
#[repr(C)]
pub struct SpecializationMapEntry {
    /// Identifier of the constant in the shader that corresponds to this field.
    pub constant_id: u32,
    /// Offset within this struct for the data.
    pub offset: u32,
    /// Size of the data in bytes.
    pub size: usize,
}
<|endoftext|>


<commit_before>//! Compute the QR-factorization of a rectangular matrix.
//!
//! An (m x n) rectangular matrix `A` is factored into the produce `Q` * `R`, such that
//!
//! - The columns of `Q` are orthonormal, and the span of the first
//! `k` columns of `Q` contains the subspaces spanned by the first `k`
//! columns of `A`, for all 1 <= `k` <= n.
//!
//! - `R` is an upper triangular or upper-trapezoidal matrix.

use impl_prelude::*;
use lapack::c::{sgeqrf, sorgqr, dgeqrf, dorgqr, cgeqrf, cungqr, zgeqrf, zungqr};
use ndarray as nd;
use num_traits::Zero;

/// Error for QR-based computations.
#[derive(Debug, Clone)]
pub enum QRError {
    /// The layout of the matrix is not compatible
    BadLayout,

    /// The dimensions of the raw qr and tau don't match
    InconsistentDimensions,

    /// Implementation error, please submit as bug.
    IllegalParameter(i32),
}

/// Representation of the components Q, R of the factorization of
/// matrix A.
#[derive(Debug)]
pub struct QRFactors<T: QR> {
    mat: Array<T, Ix2>,
    tau: Vec<T>,
}

impl<T: QR> QRFactors<T> {
    /// Create a `QRFactors` object from the output of the LAPACKE
    /// functions.
    fn from_raw<Matrix>(mat: Matrix, tau: Vec<T>) -> Result<QRFactors<T>, QRError>
        where Matrix: Into<Array<T, Ix2>>
    {
        let mut ma = mat.into();

        if slice_and_layout_mut(&mut ma).is_none() {
            return Err(QRError::BadLayout);
        }

        Ok(QRFactors {
            mat: ma,
            tau: tau,
        })
    }

    /// Given a matrix, compute the QR decomposition of the matrix,
    /// returned as a `QRFactors` object.
    pub fn compute<D1: Data<Elem=T>>(mat: &ArrayBase<D1, Ix2>)
                                     -> Result<QRFactors<T>, QRError> {
        QR::compute(mat)
    }

    /// Return the number of rows in the original matrix
    pub fn rows(&self) -> usize {
        self.mat.rows()
    }

    /// Return the number of columns in the original matrix
    pub fn cols(&self) -> usize {
        self.mat.cols()
    }

    fn p(&self) -> usize {
        cmp::min(self.rows(), self.cols())
    }

    /// Return the first `k` columns of the matrix Q of the QR
    /// factorization.
    ///
    /// `Q` is generated such that the columns of `Q` form an
    /// orthogonal basis for the first `k` columns of `A`.
    ///
    /// When `k` is None, compute enough columns (`min(m, n)`) to
    /// faithfully recreate the original matrix A.
    pub fn qk<K: Into<Option<usize>>>(&self, k: K) -> Result<Array<T, Ix2>, QRError> {
        let kr = k.into();
        QR::compute_q(&self.mat, &self.tau, kr.unwrap_or(self.p()))
    }

    /// Return the `m` by `min(m, n)` matrix `Q`.
    ///
    /// Equivalent to `self.qk(None)`.
    ///
    /// `self.q()` is large enough so that `&self.q() * &self.r()`
    /// will faithfully reproduce the original matrix `A`.
    #[inline]
    pub fn q(&self) -> Array<T, Ix2> {
        self.qk(None).expect("Invalid implementation of Self::qk. Please report.")
    }

    /// Return the first 'k' rows of the matrix R of the QR
    /// factorization.
    ///
    /// When `k` is None, compute enough rows (`min(m, n)`) to
    /// faithfully recreate the original matrix A.
    pub fn rk<K: Into<Option<usize>>>(&self, k: K) -> Result<Array<T, Ix2>, QRError> {
        let kr = k.into();
        let p = kr.unwrap_or(self.p());
        QR::compute_r(&self.mat, p)
    }

    /// Return the first `min(m, n)` by `n` matrix R of the QR
    /// factorization.
    ///
    /// Equivalent to `self::rk(None)`.
    ///
    /// `self.r()` is large enough so that `&self.q() * &self.r()`
    /// will faithfully reproduce the original matrix `A`.
    #[inline]
    pub fn r(&self) -> Array<T, Ix2> {
        self.rk(None).expect("Invalid implementation of Self::rk. Please report.")
    }

    /// Reconstruct the original matrix `A` from the factorization.
    pub fn reconstruct(&self) -> Array<T, Ix2> {
        self.q().dot(&self.r())
    }
}

/// Trait defined on scalars to support QR-factorization.
pub trait QR: nd::LinalgScalar {
    /// Return a `QRFactors` structure, containing the QR
    /// factorization of the input matrix `A`.
    ///
    /// Similar to `compute`, but consumes the input.
    fn compute_into(a: Array<Self, Ix2>) -> Result<QRFactors<Self>, QRError>;

    /// Return a `QRFactors` structure, containing the QR
    /// factorization of the input matrix `A`.
    fn compute<D1: Data>(a: &ArrayBase<D1, Ix2>) -> Result<QRFactors<Self>, QRError>
        where D1: Data<Elem = Self>
    {
        Self::compute_into(a.to_owned())
    }

    /// Compute Q from raw parts.
    ///
    /// Not intended to be used by end-users.
    fn compute_q<D1>(mat: &ArrayBase<D1, Ix2>,
                     tau: &[Self],
                     k: usize)
                     -> Result<Array<Self, Ix2>, QRError>
        where D1: Data<Elem = Self>;

    /// Compute R from raw parts.
    ///
    /// Not intended to be used by end-users.
    fn compute_r<D1>(mat: &ArrayBase<D1, Ix2>, k: usize) -> Result<Array<Self, Ix2>, QRError>
        where D1: Data<Elem = Self>;
}

macro_rules! impl_qr {
    ($qr_type:ty, $qr_func:ident, $qr_to_q:ident) => (

        impl QR for $qr_type {
            fn compute_into(mut a: Array<Self, Ix2>) -> Result<QRFactors<Self>, QRError> {
                let dim = a.dim();

                let (info, tau) = {
                    let (mut slice, layout, lda) = match slice_and_layout_mut(&mut a) {
                        None => return Err(QRError::BadLayout),
                        Some(x) => x,
                    };

                    let mut tau = Vec::new();
                    tau.resize(cmp::min(dim.0, dim.1), <$qr_type as Zero>::zero());

                    // workspace query
                    ($qr_func(layout,
                            dim.0 as i32,
                            dim.1 as i32,
                            &mut slice,
                            lda as i32,
                            &mut tau),
                     tau)
                };

                println!("{:?}\n {:?}\n", a, tau);

                if info == 0 {
                    QRFactors::from_raw(a, tau)
                } else if info < 0 {
                    Err(QRError::IllegalParameter(-info))
                } else {
                    unreachable!();
                }
            }

            fn compute_q<D1>(mat: &ArrayBase<D1, Ix2>,
                             tau: &[Self],
                             k: usize)
                             -> Result<Array<Self, Ix2>, QRError>
                where D1: Data<Elem = Self>
            {

                let (m, n) = mat.dim();
                if k > m {
                    return Err(QRError::InconsistentDimensions);
                }

                // Initialize q with the
                let mut q = mat.slice(s![.., ..k as isize]).to_owned();

                let info = {
                    let (slice, layout, ldq) = match slice_and_layout_mut(&mut q) {
                        None => unreachable!(),
                        Some(fwd) => fwd,
                    };

                    $qr_to_q(layout,
                           m as i32,
                           k as i32,
                           cmp::min(k, n) as i32,
                           slice,
                           ldq as i32,
                           tau)
                };
                if info == 0 {
                    Ok(q)
                } else {
                    Err(QRError::IllegalParameter(-info))
                }
            }

            fn compute_r<D1>(mat: &ArrayBase<D1, Ix2>, k: usize) -> Result<Array<Self, Ix2>, QRError>
                where D1: Data<Elem = Self>
            {
                let (m, n) = mat.dim();

                let nn = cmp::min(m, n);
                if k > nn {
                    return Err(QRError::InconsistentDimensions);
                }

                let mut r = Array::zeros((k as usize, n));

                // Copy the upper triangular/trapezoidal part of the matrix to
                // R.
                r.slice_mut(s![..k as isize, ..]).assign(&mat.slice(s![..k as isize, ..]));

                let zero = <$qr_type as Zero>::zero();

                // Replace zeros below the diagonal.
                for (i, mut row) in r.outer_iter_mut().enumerate().take(nn as usize) {
                    row.slice_mut(s![..i as isize]).assign_scalar(&zero);
                }

                Ok(r)
            }
        }
    )
}

impl_qr!(f32, sgeqrf, sorgqr);
impl_qr!(f64, dgeqrf, dorgqr);
impl_qr!(c32, cgeqrf, cungqr);
impl_qr!(c64, zgeqrf, zungqr);
<commit_msg>derive  PartialEq, Eq for QRError<commit_after>//! Compute the QR-factorization of a rectangular matrix.
//!
//! An (m x n) rectangular matrix `A` is factored into the produce `Q` * `R`, such that
//!
//! - The columns of `Q` are orthonormal, and the span of the first
//! `k` columns of `Q` contains the subspaces spanned by the first `k`
//! columns of `A`, for all 1 <= `k` <= n.
//!
//! - `R` is an upper triangular or upper-trapezoidal matrix.

use impl_prelude::*;
use lapack::c::{sgeqrf, sorgqr, dgeqrf, dorgqr, cgeqrf, cungqr, zgeqrf, zungqr};
use ndarray as nd;
use num_traits::Zero;

/// Error for QR-based computations.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum QRError {
    /// The layout of the matrix is not compatible
    BadLayout,

    /// The dimensions of the raw qr and tau don't match
    InconsistentDimensions,

    /// Implementation error, please submit as bug.
    IllegalParameter(i32),
}

/// Representation of the components Q, R of the factorization of
/// matrix A.
#[derive(Debug)]
pub struct QRFactors<T: QR> {
    mat: Array<T, Ix2>,
    tau: Vec<T>,
}

impl<T: QR> QRFactors<T> {
    /// Create a `QRFactors` object from the output of the LAPACKE
    /// functions.
    fn from_raw<Matrix>(mat: Matrix, tau: Vec<T>) -> Result<QRFactors<T>, QRError>
        where Matrix: Into<Array<T, Ix2>>
    {
        let mut ma = mat.into();

        if slice_and_layout_mut(&mut ma).is_none() {
            return Err(QRError::BadLayout);
        }

        Ok(QRFactors {
            mat: ma,
            tau: tau,
        })
    }

    /// Given a matrix, compute the QR decomposition of the matrix,
    /// returned as a `QRFactors` object.
    pub fn compute<D1: Data<Elem=T>>(mat: &ArrayBase<D1, Ix2>)
                                     -> Result<QRFactors<T>, QRError> {
        QR::compute(mat)
    }

    /// Return the number of rows in the original matrix
    pub fn rows(&self) -> usize {
        self.mat.rows()
    }

    /// Return the number of columns in the original matrix
    pub fn cols(&self) -> usize {
        self.mat.cols()
    }

    fn p(&self) -> usize {
        cmp::min(self.rows(), self.cols())
    }

    /// Return the first `k` columns of the matrix Q of the QR
    /// factorization.
    ///
    /// `Q` is generated such that the columns of `Q` form an
    /// orthogonal basis for the first `k` columns of `A`.
    ///
    /// When `k` is None, compute enough columns (`min(m, n)`) to
    /// faithfully recreate the original matrix A.
    pub fn qk<K: Into<Option<usize>>>(&self, k: K) -> Result<Array<T, Ix2>, QRError> {
        let kr = k.into();
        QR::compute_q(&self.mat, &self.tau, kr.unwrap_or(self.p()))
    }

    /// Return the `m` by `min(m, n)` matrix `Q`.
    ///
    /// Equivalent to `self.qk(None)`.
    ///
    /// `self.q()` is large enough so that `&self.q() * &self.r()`
    /// will faithfully reproduce the original matrix `A`.
    #[inline]
    pub fn q(&self) -> Array<T, Ix2> {
        self.qk(None).expect("Invalid implementation of Self::qk. Please report.")
    }

    /// Return the first 'k' rows of the matrix R of the QR
    /// factorization.
    ///
    /// When `k` is None, compute enough rows (`min(m, n)`) to
    /// faithfully recreate the original matrix A.
    pub fn rk<K: Into<Option<usize>>>(&self, k: K) -> Result<Array<T, Ix2>, QRError> {
        let kr = k.into();
        let p = kr.unwrap_or(self.p());
        QR::compute_r(&self.mat, p)
    }

    /// Return the first `min(m, n)` by `n` matrix R of the QR
    /// factorization.
    ///
    /// Equivalent to `self::rk(None)`.
    ///
    /// `self.r()` is large enough so that `&self.q() * &self.r()`
    /// will faithfully reproduce the original matrix `A`.
    #[inline]
    pub fn r(&self) -> Array<T, Ix2> {
        self.rk(None).expect("Invalid implementation of Self::rk. Please report.")
    }

    /// Reconstruct the original matrix `A` from the factorization.
    pub fn reconstruct(&self) -> Array<T, Ix2> {
        self.q().dot(&self.r())
    }
}

/// Trait defined on scalars to support QR-factorization.
pub trait QR: nd::LinalgScalar {
    /// Return a `QRFactors` structure, containing the QR
    /// factorization of the input matrix `A`.
    ///
    /// Similar to `compute`, but consumes the input.
    fn compute_into(a: Array<Self, Ix2>) -> Result<QRFactors<Self>, QRError>;

    /// Return a `QRFactors` structure, containing the QR
    /// factorization of the input matrix `A`.
    fn compute<D1: Data>(a: &ArrayBase<D1, Ix2>) -> Result<QRFactors<Self>, QRError>
        where D1: Data<Elem = Self>
    {
        Self::compute_into(a.to_owned())
    }

    /// Compute Q from raw parts.
    ///
    /// Not intended to be used by end-users.
    fn compute_q<D1>(mat: &ArrayBase<D1, Ix2>,
                     tau: &[Self],
                     k: usize)
                     -> Result<Array<Self, Ix2>, QRError>
        where D1: Data<Elem = Self>;

    /// Compute R from raw parts.
    ///
    /// Not intended to be used by end-users.
    fn compute_r<D1>(mat: &ArrayBase<D1, Ix2>, k: usize) -> Result<Array<Self, Ix2>, QRError>
        where D1: Data<Elem = Self>;
}

macro_rules! impl_qr {
    ($qr_type:ty, $qr_func:ident, $qr_to_q:ident) => (

        impl QR for $qr_type {
            fn compute_into(mut a: Array<Self, Ix2>) -> Result<QRFactors<Self>, QRError> {
                let dim = a.dim();

                let (info, tau) = {
                    let (mut slice, layout, lda) = match slice_and_layout_mut(&mut a) {
                        None => return Err(QRError::BadLayout),
                        Some(x) => x,
                    };

                    let mut tau = Vec::new();
                    tau.resize(cmp::min(dim.0, dim.1), <$qr_type as Zero>::zero());

                    // workspace query
                    ($qr_func(layout,
                            dim.0 as i32,
                            dim.1 as i32,
                            &mut slice,
                            lda as i32,
                            &mut tau),
                     tau)
                };

                println!("{:?}\n {:?}\n", a, tau);

                if info == 0 {
                    QRFactors::from_raw(a, tau)
                } else if info < 0 {
                    Err(QRError::IllegalParameter(-info))
                } else {
                    unreachable!();
                }
            }

            fn compute_q<D1>(mat: &ArrayBase<D1, Ix2>,
                             tau: &[Self],
                             k: usize)
                             -> Result<Array<Self, Ix2>, QRError>
                where D1: Data<Elem = Self>
            {

                let (m, n) = mat.dim();
                if k > m {
                    return Err(QRError::InconsistentDimensions);
                }

                // Initialize q with the
                let mut q = mat.slice(s![.., ..k as isize]).to_owned();

                let info = {
                    let (slice, layout, ldq) = match slice_and_layout_mut(&mut q) {
                        None => unreachable!(),
                        Some(fwd) => fwd,
                    };

                    $qr_to_q(layout,
                           m as i32,
                           k as i32,
                           cmp::min(k, n) as i32,
                           slice,
                           ldq as i32,
                           tau)
                };
                if info == 0 {
                    Ok(q)
                } else {
                    Err(QRError::IllegalParameter(-info))
                }
            }

            fn compute_r<D1>(mat: &ArrayBase<D1, Ix2>, k: usize) -> Result<Array<Self, Ix2>, QRError>
                where D1: Data<Elem = Self>
            {
                let (m, n) = mat.dim();

                let nn = cmp::min(m, n);
                if k > nn {
                    return Err(QRError::InconsistentDimensions);
                }

                let mut r = Array::zeros((k as usize, n));

                // Copy the upper triangular/trapezoidal part of the matrix to
                // R.
                r.slice_mut(s![..k as isize, ..]).assign(&mat.slice(s![..k as isize, ..]));

                let zero = <$qr_type as Zero>::zero();

                // Replace zeros below the diagonal.
                for (i, mut row) in r.outer_iter_mut().enumerate().take(nn as usize) {
                    row.slice_mut(s![..i as isize]).assign_scalar(&zero);
                }

                Ok(r)
            }
        }
    )
}

impl_qr!(f32, sgeqrf, sorgqr);
impl_qr!(f64, dgeqrf, dorgqr);
impl_qr!(c32, cgeqrf, cungqr);
impl_qr!(c64, zgeqrf, zungqr);
<|endoftext|>


<commit_before>// Copyright 2016 Revolution Solid & Contributors.
// author(s): sysnett
// rust-monster is licensed under a MIT License.

//! Genetic Algorithm Population

use super::ga_core::GAIndividual;

use std::cmp::Ordering;
use std::iter::FromIterator;

// Better name than 'Basis'?
#[derive(Clone, Copy)]
pub enum GAPopulationSortBasis
{
    Raw,
    Fitness,
}

// The 'Copy' trait requires the 'Clone' trait.
// 'Copy' removes the 'move' semantics from an assignment or a function return of value.
#[derive(Clone, Copy)]
pub enum GAPopulationSortOrder
{
    LowIsBest,
    HighIsBest,
}

/// Genetic Algorithm Population
pub struct GAPopulation<T: GAIndividual>
{
    population: Vec<T>,

    sort_order: GAPopulationSortOrder,

    // 'population' ordered by raw score.
    population_order_raw: Vec<usize>,
    // Is 'population_order_raw' sorted?
    is_raw_sorted: bool,

    // 'population' ordered by fitness score.
    population_order_fitness: Vec<usize>,
    // Is 'population_order_fitness' sorted?
    is_fitness_sorted: bool,

    // We keep 2 lists of indexes to the population vector.
    // One sorted by raw score and one by fitness score.
}
impl<T: GAIndividual> GAPopulation<T>
{
    // TODO: New should use some parameters, maybe a Config
    pub fn new(p: Vec<T>, order: GAPopulationSortOrder) -> GAPopulation<T>
    {
        let gap = GAPopulation
                  {
                      population: p,
                      sort_order: order,
                      population_order_raw: vec![],
                      is_raw_sorted: false,
                      population_order_fitness: vec![],
                      is_fitness_sorted: false
                  };

        gap
    }

    pub fn population(&mut self) -> &mut Vec<T>
    {
        return &mut self.population
    }

    pub fn evaluate(&mut self)
    {
        for ref mut ind in &mut self.population
        {
            ind.evaluate();
        }
    }

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

    pub fn order(&self) -> GAPopulationSortOrder
    {
        // This is not a 'move', but a copy (GAPopulationSortOrder implements the
        // 'Copy' trait). A move from a borrowed reference (such as 'self') would
        // not be permitted.
        self.sort_order
    }

    //TODO: this is a temporary implementation
    pub fn select(&self) -> &T
    {
        self.individual(0, GAPopulationSortBasis::Fitness)
    }

    //TODO: This is a temporary implementation
    pub fn best(&self) -> &T
    {
        // TODO: Call GAPopulation.scale().

        self.individual(0, GAPopulationSortBasis::Fitness)
    }

    //TODO: This is a temporary implementation
    pub fn worst(&self) -> &T
    {
        self.individual(self.size()-1, GAPopulationSortBasis::Fitness)
    }

    pub fn best_by_raw_score(&self) -> &T
    {
        self.individual(0, GAPopulationSortBasis::Raw)
    }

    pub fn worst_by_raw_score(&self) -> &T
    {
        self.individual(self.size()-1, GAPopulationSortBasis::Fitness)
    }

    pub fn best_by_fitness_score(&self) -> &T
    {
        self.individual(0, GAPopulationSortBasis::Fitness)
    }

    pub fn worst_by_fitness_score(&self) -> &T
    {
        self.individual(self.size()-1, GAPopulationSortBasis::Fitness)
    }

    pub fn individual(&self, i : usize, sort_basis : GAPopulationSortBasis) -> &T
    {
        // TODO: Check that i makes sense
        match sort_basis
        {
            GAPopulationSortBasis::Raw
            => { &self.population[self.population_order_raw[i]] },
            GAPopulationSortBasis::Fitness
            => { &self.population[self.population_order_fitness[i]] },
        }
    }

    pub fn sort(&mut self)
    {
        self.sort_int(false, GAPopulationSortBasis::Fitness);
        self.sort_int(false, GAPopulationSortBasis::Raw);
    }

    //TODO: I hate this name
    pub fn sort_int(&mut self, force_sort: bool, sort_basis: GAPopulationSortBasis)
    {
        let mut ordered : Vec<usize> = Vec::from_iter(0..self.size());
        match sort_basis
        {
            GAPopulationSortBasis::Raw
            =>  if (!self.is_raw_sorted) || force_sort
                {
                    match self.sort_order
                    {
                        GAPopulationSortOrder::LowIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s1].score()
                                                .partial_cmp(&self.population[*s2].score()).unwrap_or(Ordering::Equal));

                        },
                        GAPopulationSortOrder::HighIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s2].score()
                                                .partial_cmp(&self.population[*s1].score()).unwrap_or(Ordering::Equal));

                        },
                    };
                    self.population_order_raw = ordered;
                    self.is_raw_sorted = true;
                },

            GAPopulationSortBasis::Fitness
            =>  if (!self.is_fitness_sorted) || force_sort
                {
                    match self.sort_order
                    {
                        GAPopulationSortOrder::LowIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s1].fitness()
                                                .partial_cmp(&self.population[*s2].fitness()).unwrap_or(Ordering::Equal));
                        },

                        GAPopulationSortOrder::HighIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s2].fitness()
                                                .partial_cmp(&self.population[*s1].fitness()).unwrap_or(Ordering::Equal));
                        }
                    };
                    self.population_order_fitness = ordered;
                    self.is_fitness_sorted = true;
                },
        };
    }

    pub fn raw_score_iterator<'a>(&'a self) -> GAPopulationRawIterator<'a, T>
    {
        GAPopulationRawIterator { population: &self, next: 0 }
    }

    pub fn fitness_score_iterator<'a>(&'a self) -> GAPopulationFitnessIterator<'a, T>
    {
        GAPopulationFitnessIterator { population: &self, next: 0 }
    }
}

pub struct GAPopulationRawIterator<'a, T: 'a + GAIndividual>
{
    population: &'a GAPopulation<T>,
    next: usize
}

impl<'a, T: GAIndividual> Iterator for GAPopulationRawIterator<'a, T>
{
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item>
    {
        if self.next == self.population.size()
        {
            None
        }
        else
        {
            self.next = self.next + 1;
            Some(self.population.individual(self.next - 1, GAPopulationSortBasis::Raw))
        }
    }
}

pub struct GAPopulationFitnessIterator<'a, T: 'a + GAIndividual>
{
    population: &'a GAPopulation<T>,
    next: usize
}

impl<'a, T: GAIndividual> Iterator for GAPopulationFitnessIterator<'a, T>
{
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item>
    {
        if self.next == self.population.size()
        {
            None
        }
        else
        {
            self.next = self.next + 1;
            Some(self.population.individual(self.next - 1, GAPopulationSortBasis::Fitness))
        }
    }

}

////////////////////////////////////////
// Tests
#[cfg(test)]
mod test
{
    use super::*;
    use super::super::ga_test::*;
    use super::super::ga_core::*;

    #[test]
    fn test_sort_population()
    {
        ga_test_setup("ga_population::test_sort_population");
        let f = GA_TEST_FITNESS_VAL;
        let f_m = GA_TEST_FITNESS_VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population = GAPopulation::new(vec![GATestIndividual::new(f), GATestIndividual::new(f_m)], GAPopulationSortOrder::HighIsBest);
        population.sort();

        //GATestIndividual's Fitness is the inverse of the Score (F = 1/S)
        assert_eq!(population.individual(0, GAPopulationSortBasis::Raw).score(), f);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Raw).score(), f_m);
        assert_eq!(population.individual(0, GAPopulationSortBasis::Fitness).fitness(), i_f_m);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Fitness).fitness(), i_f);
        ga_test_teardown();
    }

    #[test]
    fn test_population_raw_iterator()
    {
        // Iteration of a LowIsBest population yields a sequence of non-decreasing raw scores.

        let mut expected_seq: Vec<f32> = (1..10).map(|rs| rs as f32).collect();
        {
            let mut inds: Vec<GATestIndividual> = Vec::new();
            for rs in 1..10
            {
                inds.push(GATestIndividual::new(rs as f32));
            }
            let mut pop = GAPopulation::new(inds, GAPopulationSortOrder::LowIsBest);
            pop.sort();

            let it = pop.raw_score_iterator();
            let actual_seq: Vec<f32> = it.map(|ind| { ind.score() }).collect();
            assert_eq!(expected_seq, actual_seq);
        }

        // Iteration of a HighIsBest population yields a sequence of non-increasing raw scores.

        expected_seq.reverse();
        {
            let mut inds: Vec<GATestIndividual> = Vec::new();
            for rs in 1..10
            {
                inds.push(GATestIndividual::new(rs as f32));
            }
            let mut pop = GAPopulation::new(inds, GAPopulationSortOrder::HighIsBest);
            pop.sort();

            let it = pop.raw_score_iterator();
            let actual_seq: Vec<f32> = it.map(|ind| { ind.score() }).collect();
            assert_eq!(expected_seq, actual_seq);
        }
    }

    #[test]
    fn test_population_fitness_iterator()
    {
        // Iteration of a HighIsBest population yields a sequence of non-decreasing fitness scores (when fitness = 1/raw).

        let mut expected_seq: Vec<f32> = (1..10).map(|rs| 1.0/(rs as f32)).collect();
        {
            let mut inds: Vec<GATestIndividual> = Vec::new();
            for rs in 1..10
            {
                inds.push(GATestIndividual::new(rs as f32));
            }
            let mut pop = GAPopulation::new(inds, GAPopulationSortOrder::HighIsBest);
            pop.sort();

            let it = pop.fitness_score_iterator();
            let actual_seq: Vec<f32> = it.map(|ind| { ind.fitness() }).collect();
            assert_eq!(expected_seq, actual_seq);
        }

        // Iteration of a LowIsBest population yields a sequence of non-increasing fitness scores (when fitness = 1/raw).

        expected_seq.reverse();
        {
            let mut inds: Vec<GATestIndividual> = Vec::new();
            for rs in 1..10
            {
                inds.push(GATestIndividual::new(rs as f32));
            }
            let mut pop = GAPopulation::new(inds, GAPopulationSortOrder::LowIsBest);
            pop.sort();

            let it = pop.fitness_score_iterator();
            let actual_seq: Vec<f32> = it.map(|ind| { ind.fitness() }).collect();
            assert_eq!(expected_seq, actual_seq);
        }

    }
}
<commit_msg>Use Raw instead of Fitness ranking in worst_by_raw_score(). (#20)<commit_after>// Copyright 2016 Revolution Solid & Contributors.
// author(s): sysnett
// rust-monster is licensed under a MIT License.

//! Genetic Algorithm Population

use super::ga_core::GAIndividual;

use std::cmp::Ordering;
use std::iter::FromIterator;

// Better name than 'Basis'?
#[derive(Clone, Copy)]
pub enum GAPopulationSortBasis
{
    Raw,
    Fitness,
}

// The 'Copy' trait requires the 'Clone' trait.
// 'Copy' removes the 'move' semantics from an assignment or a function return of value.
#[derive(Clone, Copy)]
pub enum GAPopulationSortOrder
{
    LowIsBest,
    HighIsBest,
}

/// Genetic Algorithm Population
pub struct GAPopulation<T: GAIndividual>
{
    population: Vec<T>,

    sort_order: GAPopulationSortOrder,

    // 'population' ordered by raw score.
    population_order_raw: Vec<usize>,
    // Is 'population_order_raw' sorted?
    is_raw_sorted: bool,

    // 'population' ordered by fitness score.
    population_order_fitness: Vec<usize>,
    // Is 'population_order_fitness' sorted?
    is_fitness_sorted: bool,

    // We keep 2 lists of indexes to the population vector.
    // One sorted by raw score and one by fitness score.
}
impl<T: GAIndividual> GAPopulation<T>
{
    // TODO: New should use some parameters, maybe a Config
    pub fn new(p: Vec<T>, order: GAPopulationSortOrder) -> GAPopulation<T>
    {
        let gap = GAPopulation
                  {
                      population: p,
                      sort_order: order,
                      population_order_raw: vec![],
                      is_raw_sorted: false,
                      population_order_fitness: vec![],
                      is_fitness_sorted: false
                  };

        gap
    }

    pub fn population(&mut self) -> &mut Vec<T>
    {
        return &mut self.population
    }

    pub fn evaluate(&mut self)
    {
        for ref mut ind in &mut self.population
        {
            ind.evaluate();
        }
    }

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

    pub fn order(&self) -> GAPopulationSortOrder
    {
        // This is not a 'move', but a copy (GAPopulationSortOrder implements the
        // 'Copy' trait). A move from a borrowed reference (such as 'self') would
        // not be permitted.
        self.sort_order
    }

    //TODO: this is a temporary implementation
    pub fn select(&self) -> &T
    {
        self.individual(0, GAPopulationSortBasis::Fitness)
    }

    //TODO: This is a temporary implementation
    pub fn best(&self) -> &T
    {
        // TODO: Call GAPopulation.scale().

        self.individual(0, GAPopulationSortBasis::Fitness)
    }

    //TODO: This is a temporary implementation
    pub fn worst(&self) -> &T
    {
        self.individual(self.size()-1, GAPopulationSortBasis::Fitness)
    }

    pub fn best_by_raw_score(&self) -> &T
    {
        self.individual(0, GAPopulationSortBasis::Raw)
    }

    pub fn worst_by_raw_score(&self) -> &T
    {
        self.individual(self.size()-1, GAPopulationSortBasis::Raw)
    }

    pub fn best_by_fitness_score(&self) -> &T
    {
        self.individual(0, GAPopulationSortBasis::Fitness)
    }

    pub fn worst_by_fitness_score(&self) -> &T
    {
        self.individual(self.size()-1, GAPopulationSortBasis::Fitness)
    }

    pub fn individual(&self, i : usize, sort_basis : GAPopulationSortBasis) -> &T
    {
        // TODO: Check that i makes sense
        match sort_basis
        {
            GAPopulationSortBasis::Raw
            => { &self.population[self.population_order_raw[i]] },
            GAPopulationSortBasis::Fitness
            => { &self.population[self.population_order_fitness[i]] },
        }
    }

    pub fn sort(&mut self)
    {
        self.sort_int(false, GAPopulationSortBasis::Fitness);
        self.sort_int(false, GAPopulationSortBasis::Raw);
    }

    //TODO: I hate this name
    pub fn sort_int(&mut self, force_sort: bool, sort_basis: GAPopulationSortBasis)
    {
        let mut ordered : Vec<usize> = Vec::from_iter(0..self.size());
        match sort_basis
        {
            GAPopulationSortBasis::Raw
            =>  if (!self.is_raw_sorted) || force_sort
                {
                    match self.sort_order
                    {
                        GAPopulationSortOrder::LowIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s1].score()
                                                .partial_cmp(&self.population[*s2].score()).unwrap_or(Ordering::Equal));

                        },
                        GAPopulationSortOrder::HighIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s2].score()
                                                .partial_cmp(&self.population[*s1].score()).unwrap_or(Ordering::Equal));

                        },
                    };
                    self.population_order_raw = ordered;
                    self.is_raw_sorted = true;
                },

            GAPopulationSortBasis::Fitness
            =>  if (!self.is_fitness_sorted) || force_sort
                {
                    match self.sort_order
                    {
                        GAPopulationSortOrder::LowIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s1].fitness()
                                                .partial_cmp(&self.population[*s2].fitness()).unwrap_or(Ordering::Equal));
                        },

                        GAPopulationSortOrder::HighIsBest =>
                        {
                            ordered.sort_by(|s1: &usize, s2: &usize|
                                            self.population[*s2].fitness()
                                                .partial_cmp(&self.population[*s1].fitness()).unwrap_or(Ordering::Equal));
                        }
                    };
                    self.population_order_fitness = ordered;
                    self.is_fitness_sorted = true;
                },
        };
    }

    pub fn raw_score_iterator<'a>(&'a self) -> GAPopulationRawIterator<'a, T>
    {
        GAPopulationRawIterator { population: &self, next: 0 }
    }

    pub fn fitness_score_iterator<'a>(&'a self) -> GAPopulationFitnessIterator<'a, T>
    {
        GAPopulationFitnessIterator { population: &self, next: 0 }
    }
}

pub struct GAPopulationRawIterator<'a, T: 'a + GAIndividual>
{
    population: &'a GAPopulation<T>,
    next: usize
}

impl<'a, T: GAIndividual> Iterator for GAPopulationRawIterator<'a, T>
{
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item>
    {
        if self.next == self.population.size()
        {
            None
        }
        else
        {
            self.next = self.next + 1;
            Some(self.population.individual(self.next - 1, GAPopulationSortBasis::Raw))
        }
    }
}

pub struct GAPopulationFitnessIterator<'a, T: 'a + GAIndividual>
{
    population: &'a GAPopulation<T>,
    next: usize
}

impl<'a, T: GAIndividual> Iterator for GAPopulationFitnessIterator<'a, T>
{
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item>
    {
        if self.next == self.population.size()
        {
            None
        }
        else
        {
            self.next = self.next + 1;
            Some(self.population.individual(self.next - 1, GAPopulationSortBasis::Fitness))
        }
    }

}

////////////////////////////////////////
// Tests
#[cfg(test)]
mod test
{
    use super::*;
    use super::super::ga_test::*;
    use super::super::ga_core::*;

    #[test]
    fn test_sort_population()
    {
        ga_test_setup("ga_population::test_sort_population");
        let f = GA_TEST_FITNESS_VAL;
        let f_m = GA_TEST_FITNESS_VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population = GAPopulation::new(vec![GATestIndividual::new(f), GATestIndividual::new(f_m)], GAPopulationSortOrder::HighIsBest);
        population.sort();

        //GATestIndividual's Fitness is the inverse of the Score (F = 1/S)
        assert_eq!(population.individual(0, GAPopulationSortBasis::Raw).score(), f);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Raw).score(), f_m);
        assert_eq!(population.individual(0, GAPopulationSortBasis::Fitness).fitness(), i_f_m);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Fitness).fitness(), i_f);
        ga_test_teardown();
    }

    #[test]
    fn test_population_raw_iterator()
    {
        // Iteration of a LowIsBest population yields a sequence of non-decreasing raw scores.

        let mut expected_seq: Vec<f32> = (1..10).map(|rs| rs as f32).collect();
        {
            let mut inds: Vec<GATestIndividual> = Vec::new();
            for rs in 1..10
            {
                inds.push(GATestIndividual::new(rs as f32));
            }
            let mut pop = GAPopulation::new(inds, GAPopulationSortOrder::LowIsBest);
            pop.sort();

            let it = pop.raw_score_iterator();
            let actual_seq: Vec<f32> = it.map(|ind| { ind.score() }).collect();
            assert_eq!(expected_seq, actual_seq);
        }

        // Iteration of a HighIsBest population yields a sequence of non-increasing raw scores.

        expected_seq.reverse();
        {
            let mut inds: Vec<GATestIndividual> = Vec::new();
            for rs in 1..10
            {
                inds.push(GATestIndividual::new(rs as f32));
            }
            let mut pop = GAPopulation::new(inds, GAPopulationSortOrder::HighIsBest);
            pop.sort();

            let it = pop.raw_score_iterator();
            let actual_seq: Vec<f32> = it.map(|ind| { ind.score() }).collect();
            assert_eq!(expected_seq, actual_seq);
        }
    }

    #[test]
    fn test_population_fitness_iterator()
    {
        // Iteration of a HighIsBest population yields a sequence of non-decreasing fitness scores (when fitness = 1/raw).

        let mut expected_seq: Vec<f32> = (1..10).map(|rs| 1.0/(rs as f32)).collect();
        {
            let mut inds: Vec<GATestIndividual> = Vec::new();
            for rs in 1..10
            {
                inds.push(GATestIndividual::new(rs as f32));
            }
            let mut pop = GAPopulation::new(inds, GAPopulationSortOrder::HighIsBest);
            pop.sort();

            let it = pop.fitness_score_iterator();
            let actual_seq: Vec<f32> = it.map(|ind| { ind.fitness() }).collect();
            assert_eq!(expected_seq, actual_seq);
        }

        // Iteration of a LowIsBest population yields a sequence of non-increasing fitness scores (when fitness = 1/raw).

        expected_seq.reverse();
        {
            let mut inds: Vec<GATestIndividual> = Vec::new();
            for rs in 1..10
            {
                inds.push(GATestIndividual::new(rs as f32));
            }
            let mut pop = GAPopulation::new(inds, GAPopulationSortOrder::LowIsBest);
            pop.sort();

            let it = pop.fitness_score_iterator();
            let actual_seq: Vec<f32> = it.map(|ind| { ind.fitness() }).collect();
            assert_eq!(expected_seq, actual_seq);
        }

    }
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! GPIO configuration.

use hal::gpio::{Direction, In, Out, Level, Low, High};
use super::pin::{PinConf, Port0, Port1, Port2, Port3, Port4};

#[path="../../lib/ioreg.rs"] mod ioreg;

/// GPIO configuration.
pub struct GPIOConf {
  /// Pin configuration for this GPIO.
  pub pin: PinConf,

  /// Direction for GPIO, either `In` or `Out`.
  pub direction: Direction,
}

pub struct GPIO<'a> {
  pin: &'a PinConf,
}

impl GPIOConf {
  /// Returns a GPIO object that can be used to toggle or read GPIO value.
  pub fn setup<'a>(&'a self) -> GPIO<'a> {
    let gpio: GPIO = GPIO {
      pin: &self.pin,
    };

    gpio.set_direction(self.direction);

    gpio
  }
}

impl<'a> GPIO<'a> {
  /// Sets output GPIO value to high.
  #[inline(always)]
  pub fn set_high(&self) {
    self.reg().set_FIOSET(1 << self.pin.pin);
  }

  /// Sets output GPIO value to low.
  #[inline(always)]
  pub fn set_low(&self) {
    self.reg().set_FIOCLR(1 << self.pin.pin);
  }

  /// Sets output GPIO direction.
  #[inline(always)]
  pub fn set_direction(&self, new_mode: Direction) {
    let bit: u32 = 1 << self.pin.pin;
    let mask: u32 = !bit;
    let reg = self.reg();
    let val: u32 = reg.FIODIR();
    let new_val: u32 = match new_mode {
      In  => val & mask,
      Out => (val & mask) | bit,
    };

    reg.set_FIODIR(new_val);
  }

  /// Returns input GPIO level.
  #[inline(always)]
  pub fn level(&self) -> Level {
    let bit: u32 = 1 << self.pin.pin;
    let reg = self.reg();

    match reg.FIOPIN() & bit {
      0 => Low,
      _ => High,
    }
  }

  #[inline(always)]
  fn reg(&self) -> &reg::GPIO {
    match self.pin.port {
      Port0 => &reg::GPIO0,
      Port1 => &reg::GPIO1,
      Port2 => &reg::GPIO2,
      Port3 => &reg::GPIO3,
      Port4 => &reg::GPIO4,
    }
  }
}

mod reg {
  use lib::volatile_cell::VolatileCell;

  ioreg!(GPIO: FIODIR, _r0, _r1, _r2, FIOMASK, FIOPIN, FIOSET, FIOCLR)
  reg_rw!(GPIO, FIODIR,  set_FIODIR,  FIODIR)
  reg_rw!(GPIO, FIOMASK, set_FIOMASK, FIOMASK)
  reg_rw!(GPIO, FIOPIN,  set_FIOPIN,  FIOPIN)
  reg_rw!(GPIO, FIOSET,  set_FIOSET,  FIOSET)
  reg_rw!(GPIO, FIOCLR,  set_FIOCLR,  FIOCLR)

  extern {
    #[link_name="iomem_GPIO0"] pub static GPIO0: GPIO;
    #[link_name="iomem_GPIO1"] pub static GPIO1: GPIO;
    #[link_name="iomem_GPIO2"] pub static GPIO2: GPIO;
    #[link_name="iomem_GPIO3"] pub static GPIO3: GPIO;
    #[link_name="iomem_GPIO4"] pub static GPIO4: GPIO;
  }
}
<commit_msg>Removed forceful inlining<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! GPIO configuration.

use hal::gpio::{Direction, In, Out, Level, Low, High};
use super::pin::{PinConf, Port0, Port1, Port2, Port3, Port4};

#[path="../../lib/ioreg.rs"] mod ioreg;

/// GPIO configuration.
pub struct GPIOConf {
  /// Pin configuration for this GPIO.
  pub pin: PinConf,

  /// Direction for GPIO, either `In` or `Out`.
  pub direction: Direction,
}

pub struct GPIO<'a> {
  pin: &'a PinConf,
}

impl GPIOConf {
  /// Returns a GPIO object that can be used to toggle or read GPIO value.
  pub fn setup<'a>(&'a self) -> GPIO<'a> {
    let gpio: GPIO = GPIO {
      pin: &self.pin,
    };

    gpio.set_direction(self.direction);

    gpio
  }
}

impl<'a> GPIO<'a> {
  /// Sets output GPIO value to high.
  pub fn set_high(&self) {
    self.reg().set_FIOSET(1 << self.pin.pin);
  }

  /// Sets output GPIO value to low.
  pub fn set_low(&self) {
    self.reg().set_FIOCLR(1 << self.pin.pin);
  }

  /// Sets output GPIO direction.
  pub fn set_direction(&self, new_mode: Direction) {
    let bit: u32 = 1 << self.pin.pin;
    let mask: u32 = !bit;
    let reg = self.reg();
    let val: u32 = reg.FIODIR();
    let new_val: u32 = match new_mode {
      In  => val & mask,
      Out => (val & mask) | bit,
    };

    reg.set_FIODIR(new_val);
  }

  /// Returns input GPIO level.
  pub fn level(&self) -> Level {
    let bit: u32 = 1 << self.pin.pin;
    let reg = self.reg();

    match reg.FIOPIN() & bit {
      0 => Low,
      _ => High,
    }
  }

  fn reg(&self) -> &reg::GPIO {
    match self.pin.port {
      Port0 => &reg::GPIO0,
      Port1 => &reg::GPIO1,
      Port2 => &reg::GPIO2,
      Port3 => &reg::GPIO3,
      Port4 => &reg::GPIO4,
    }
  }
}

mod reg {
  use lib::volatile_cell::VolatileCell;

  ioreg!(GPIO: FIODIR, _r0, _r1, _r2, FIOMASK, FIOPIN, FIOSET, FIOCLR)
  reg_rw!(GPIO, FIODIR,  set_FIODIR,  FIODIR)
  reg_rw!(GPIO, FIOMASK, set_FIOMASK, FIOMASK)
  reg_rw!(GPIO, FIOPIN,  set_FIOPIN,  FIOPIN)
  reg_rw!(GPIO, FIOSET,  set_FIOSET,  FIOSET)
  reg_rw!(GPIO, FIOCLR,  set_FIOCLR,  FIOCLR)

  extern {
    #[link_name="iomem_GPIO0"] pub static GPIO0: GPIO;
    #[link_name="iomem_GPIO1"] pub static GPIO1: GPIO;
    #[link_name="iomem_GPIO2"] pub static GPIO2: GPIO;
    #[link_name="iomem_GPIO3"] pub static GPIO3: GPIO;
    #[link_name="iomem_GPIO4"] pub static GPIO4: GPIO;
  }
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! GPIO configuration.

use hal::gpio::{Direction, In, Out, Level, Low, High};
use super::pin::{PinConf, Port0, Port1, Port2, Port3, Port4};

#[path="../../lib/ioreg.rs"] mod ioreg;

/// GPIO configuration.
pub struct GPIOConf {
  /// Pin configuration for this GPIO.
  pub pin: PinConf,

  /// Direction for GPIO, either `In` or `Out`.
  pub direction: Direction,
}

impl GPIOConf {
  /// Returns a GPIO object (actually -- self), that can be used to toggle or
  /// read GPIO value.
  pub fn setup<'a>(&'a self) -> &'a GPIOConf {
    self.set_mode(self.direction);

    self
  }

  /// Sets output GPIO value to high.
  pub fn set_high(&self) {
    self.reg().set_FIOSET(1 << self.pin.pin);
  }

  /// Sets output GPIO value to low.
  pub fn set_low(&self) {
    self.reg().set_FIOCLR(1 << self.pin.pin);
  }

  /// Sets output GPIO direction.
  pub fn set_direction(&self, new_mode: Direction) {
    let bit: u32 = 1 << self.pin.pin;
    let mask: u32 = !bit;
    let reg = self.reg();
    let val: u32 = reg.FIODIR();
    let new_val: u32 = match new_mode {
      In  => val & mask,
      Out => (val & mask) | bit,
    };

    reg.set_FIODIR(new_val);
  }

  /// Returns input GPIO level.
  pub fn level(&self) -> Level {
    let bit: u32 = 1 << self.pin.pin;
    let reg = self.reg();

    match reg.FIOPIN() & bit {
      0 => Low,
      _ => High,
    }
  }

  fn reg(&self) -> &reg::GPIO {
    match self.pin.port {
      Port0 => &reg::GPIO0,
      Port1 => &reg::GPIO1,
      Port2 => &reg::GPIO2,
      Port3 => &reg::GPIO3,
      Port4 => &reg::GPIO4,
    }
  }
}

mod reg {
  use lib::volatile_cell::VolatileCell;

  ioreg!(GPIO: FIODIR, _r0, _r1, _r2, FIOMASK, FIOPIN, FIOSET, FIOCLR)
  reg_rw!(GPIO, FIODIR,  set_FIODIR,  FIODIR)
  reg_rw!(GPIO, FIOMASK, set_FIOMASK, FIOMASK)
  reg_rw!(GPIO, FIOPIN,  set_FIOPIN,  FIOPIN)
  reg_rw!(GPIO, FIOSET,  set_FIOSET,  FIOSET)
  reg_rw!(GPIO, FIOCLR,  set_FIOCLR,  FIOCLR)

  extern {
    #[link_name="iomem_GPIO0"] pub static GPIO0: GPIO;
    #[link_name="iomem_GPIO1"] pub static GPIO1: GPIO;
    #[link_name="iomem_GPIO2"] pub static GPIO2: GPIO;
    #[link_name="iomem_GPIO3"] pub static GPIO3: GPIO;
    #[link_name="iomem_GPIO4"] pub static GPIO4: GPIO;
  }
}
<commit_msg>Fixed misnamed getter in gpio code.<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! GPIO configuration.

use hal::gpio::{Direction, In, Out, Level, Low, High};
use super::pin::{PinConf, Port0, Port1, Port2, Port3, Port4};

#[path="../../lib/ioreg.rs"] mod ioreg;

/// GPIO configuration.
pub struct GPIOConf {
  /// Pin configuration for this GPIO.
  pub pin: PinConf,

  /// Direction for GPIO, either `In` or `Out`.
  pub direction: Direction,
}

impl GPIOConf {
  /// Returns a GPIO object (actually -- self), that can be used to toggle or
  /// read GPIO value.
  pub fn setup<'a>(&'a self) -> &'a GPIOConf {
    self.set_direction(self.direction);

    self
  }

  /// Sets output GPIO value to high.
  pub fn set_high(&self) {
    self.reg().set_FIOSET(1 << self.pin.pin);
  }

  /// Sets output GPIO value to low.
  pub fn set_low(&self) {
    self.reg().set_FIOCLR(1 << self.pin.pin);
  }

  /// Sets output GPIO direction.
  pub fn set_direction(&self, new_mode: Direction) {
    let bit: u32 = 1 << self.pin.pin;
    let mask: u32 = !bit;
    let reg = self.reg();
    let val: u32 = reg.FIODIR();
    let new_val: u32 = match new_mode {
      In  => val & mask,
      Out => (val & mask) | bit,
    };

    reg.set_FIODIR(new_val);
  }

  /// Returns input GPIO level.
  pub fn level(&self) -> Level {
    let bit: u32 = 1 << self.pin.pin;
    let reg = self.reg();

    match reg.FIOPIN() & bit {
      0 => Low,
      _ => High,
    }
  }

  fn reg(&self) -> &reg::GPIO {
    match self.pin.port {
      Port0 => &reg::GPIO0,
      Port1 => &reg::GPIO1,
      Port2 => &reg::GPIO2,
      Port3 => &reg::GPIO3,
      Port4 => &reg::GPIO4,
    }
  }
}

mod reg {
  use lib::volatile_cell::VolatileCell;

  ioreg!(GPIO: FIODIR, _r0, _r1, _r2, FIOMASK, FIOPIN, FIOSET, FIOCLR)
  reg_rw!(GPIO, FIODIR,  set_FIODIR,  FIODIR)
  reg_rw!(GPIO, FIOMASK, set_FIOMASK, FIOMASK)
  reg_rw!(GPIO, FIOPIN,  set_FIOPIN,  FIOPIN)
  reg_rw!(GPIO, FIOSET,  set_FIOSET,  FIOSET)
  reg_rw!(GPIO, FIOCLR,  set_FIOCLR,  FIOCLR)

  extern {
    #[link_name="iomem_GPIO0"] pub static GPIO0: GPIO;
    #[link_name="iomem_GPIO1"] pub static GPIO1: GPIO;
    #[link_name="iomem_GPIO2"] pub static GPIO2: GPIO;
    #[link_name="iomem_GPIO3"] pub static GPIO3: GPIO;
    #[link_name="iomem_GPIO4"] pub static GPIO4: GPIO;
  }
}
<|endoftext|>