<commit_before>//! Most simple engine that runs evolution
//! sequentially. Useful for test purposes
//! and with grids which implemented interior parallelism.

use traits::Cell;
use traits::Consumer;
use traits::Grid;
use traits::Engine;

pub struct Sequential<C: Cell, G: Grid<Cell = C>, Con: Consumer<Cell = C>> {
    grid: G,
    consumer: Con,
}

impl<C: Cell, G: Grid<Cell = C>, Con: Consumer<Cell = C>> Sequential<C, G, Con> {
    pub fn new(grid: G, consumer: Con) -> Self {
        Sequential {
            grid: grid,
            consumer: consumer,
        }
    }
}

impl<C: Cell, G: Grid<Cell = C>, Con: Consumer<Cell = C>> Engine for Sequential<C, G, Con> {
    fn run_times(&mut self, times: i64) {
        for _ in 0..times {
            self.grid.update();
            self.consumer.consume(&mut self.grid);
        }
    }
}
<commit_msg>Note about struct and constructor.<commit_after>//! Most simple engine that runs evolution
//! sequentially. Useful for test purposes
//! and with grids which implemented interior parallelism.

use traits::Cell;
use traits::Consumer;
use traits::Grid;
use traits::Engine;

/// Engine generic over Cell and Consumer running
/// evolution sequentially.
pub struct Sequential<C: Cell, G: Grid<Cell = C>, Con: Consumer<Cell = C>> {
    grid: G,
    consumer: Con,
}

impl<C: Cell, G: Grid<Cell = C>, Con: Consumer<Cell = C>> Sequential<C, G, Con> {

    /// Constructs engine with given Grid and Consumer.
    pub fn new(grid: G, consumer: Con) -> Self {
        Sequential {
            grid: grid,
            consumer: consumer,
        }
    }
}

impl<C: Cell, G: Grid<Cell = C>, Con: Consumer<Cell = C>> Engine for Sequential<C, G, Con> {
    fn run_times(&mut self, times: i64) {
        for _ in 0..times {
            self.grid.update();
            self.consumer.consume(&mut self.grid);
        }
    }
}
<|endoftext|>


<commit_before>extern crate gcc;

use std::process::{Command, Stdio};
use std::env;

fn main() {
    // 1. Build the object file from source using node-gyp.
    build_object_file();

    // 2. Link the library from the object file using gcc.
    link_library();
}

fn build_object_file() {
    let npm_command = if cfg!(unix) { "npm" } else { "npm.cmd" };
    let node_gyp_command = if cfg!(unix) { "node-gyp" } else { "node-gyp.cmd" };

    // Ensure that all package.json dependencies and dev dependencies are installed.
    Command::new(npm_command).args(&["install", "--silent"]).status().ok().expect("Failed to run \"npm install\" for neon-sys!");

    // Run `node-gyp configure` with correct debug and architecture flags
    let mut configure_args = vec!["configure"];
    if debug() {
        configure_args.push("--debug")
    }
    let target = env::var("TARGET").unwrap();
    if target.contains("i686") || target.contains("i586") {
        configure_args.push("--arch=ia32");
    } else if target.contains("x86_64") {
        configure_args.push("--arch=x64");
    }

    let output = Command::new(node_gyp_command)
        .args(&configure_args)
        .output()
        .expect("Failed to run \"node-gyp configure\" for neon-sys!");

    if cfg!(windows) {
        let node_gyp_output = String::from_utf8_lossy(&output.stderr);
        let node_root_dir_flag_pattern = "'-Dnode_root_dir=";
        let node_root_dir_start_index = node_gyp_output
            .find(node_root_dir_flag_pattern)
            .map(|i| i + node_root_dir_flag_pattern.len())
            .expect("Couldn't find node_root_dir in node-gyp output.");
        let node_root_dir_end_index = node_gyp_output[node_root_dir_start_index..].find("'").unwrap() + node_root_dir_start_index;
        println!("cargo:node_root_dir={}", &node_gyp_output[node_root_dir_start_index..node_root_dir_end_index]);
    }

    // Run `node-gyp build` (appending -d in debug mode).
    let build_args = if debug() { vec!["build", "-d"] } else { vec!["build"] };
    Command::new(node_gyp_command)
        .stderr(Stdio::null()) // Prevent cargo build from hanging on Windows.
        .args(&build_args)
        .status()
        .ok()
        .expect("Failed to run \"node-gyp build\" for neon-sys!");
}

// Link the built object file into a static library.
fn link_library() {
    let configuration = if debug() { "Debug" } else { "Release" };
    let object_path = if cfg!(unix) {
        format!("build/{}/obj.target/neon/src/neon.o", configuration)
    } else {
        format!("build\\{}\\obj\\neon\\neon.obj", configuration)
    };

    gcc::Config::new().object(object_path).compile("libneon.a");
}

fn debug() -> bool {
    match env::var("DEBUG") {
        Ok(s) => s == "true",
        Err(_) => false
    }
}
<commit_msg>Downcase npm environment variables to ensure they are read by node-gyp<commit_after>extern crate gcc;

use std::process::{Command, Stdio};
use std::env;

fn main() {
    // 1. Build the object file from source using node-gyp.
    build_object_file();

    // 2. Link the library from the object file using gcc.
    link_library();
}

fn build_object_file() {
    let npm_command = if cfg!(unix) { "npm" } else { "npm.cmd" };
    let node_gyp_command = if cfg!(unix) { "node-gyp" } else { "node-gyp.cmd" };

    if cfg!(windows) {
        // Downcase all the npm environment variables to ensure they are read by node-gyp.
        for (key, value) in env::vars() {
            if key.starts_with("NPM_CONFIG") {
                env::remove_var(&key);
                env::set_var(key.to_lowercase(), value);
            }
        }
    }

    // Ensure that all package.json dependencies and dev dependencies are installed.
    Command::new(npm_command).args(&["install", "--silent"]).status().ok().expect("Failed to run \"npm install\" for neon-sys!");

    // Run `node-gyp configure` in verbose mode to read node_root_dir on Windows.
    let mut configure_args = vec!["configure", "--verbose"];
    if debug() {
        configure_args.push("--debug");
    }

    let output = Command::new(node_gyp_command)
        .args(&configure_args)
        .output()
        .expect("Failed to run \"node-gyp configure\" for neon-sys!");

    if cfg!(windows) {
        let node_gyp_output = String::from_utf8_lossy(&output.stderr);
        let node_root_dir_flag_pattern = "'-Dnode_root_dir=";
        let node_root_dir_start_index = node_gyp_output
            .find(node_root_dir_flag_pattern)
            .map(|i| i + node_root_dir_flag_pattern.len())
            .expect("Couldn't find node_root_dir in node-gyp output.");
        let node_root_dir_end_index = node_gyp_output[node_root_dir_start_index..].find("'").unwrap() + node_root_dir_start_index;
        println!("cargo:node_root_dir={}", &node_gyp_output[node_root_dir_start_index..node_root_dir_end_index]);
    }

    // Run `node-gyp build` (appending -d in debug mode).
    let mut build_args = vec!["build"];
    if debug() {
        build_args.push("--debug");
    }

    Command::new(node_gyp_command)
        .stderr(Stdio::null()) // Prevent cargo build from hanging on Windows.
        .args(&build_args)
        .status()
        .ok()
        .expect("Failed to run \"node-gyp build\" for neon-sys!");
}

// Link the built object file into a static library.
fn link_library() {
    let configuration = if debug() { "Debug" } else { "Release" };
    let object_path = if cfg!(unix) {
        format!("build/{}/obj.target/neon/src/neon.o", configuration)
    } else {
        format!("build\\{}\\obj\\neon\\neon.obj", configuration)
    };

    gcc::Config::new().object(object_path).compile("libneon.a");
}

fn debug() -> bool {
    match env::var("DEBUG") {
        Ok(s) => s == "true",
        Err(_) => false
    }
}
<|endoftext|>


<commit_before>//! Routing and runtime macros for Actix Web.
//!
//! # Actix Web Re-exports
//! Actix Web re-exports a version of this crate in it's entirety so you usually don't have to
//! specify a dependency on this crate explicitly. Sometimes, however, updates are made to this
//! crate before the actix-web dependency is updated. Therefore, code examples here will show
//! explicit imports. Check the latest [actix-web attributes docs] to see which macros
//! are re-exported.
//!
//! # Runtime Setup
//! Used for setting up the actix async runtime. See [macro@main] macro docs.
//!
//! ```
//! #[actix_web_codegen::main] // or `#[actix_web::main]` in Actix Web apps
//! async fn main() {
//!     async { println!("Hello world"); }.await
//! }
//! ```
//!
//! # Single Method Handler
//! There is a macro to set up a handler for each of the most common HTTP methods that also define
//! additional guards and route-specific middleware.
//!
//! See docs for: [GET], [POST], [PATCH], [PUT], [DELETE], [HEAD], [CONNECT], [OPTIONS], [TRACE]
//!
//! ```
//! # use actix_web::HttpResponse;
//! # use actix_web_codegen::get;
//! #[get("/test")]
//! async fn get_handler() -> HttpResponse {
//!     HttpResponse::Ok().finish()
//! }
//! ```
//!
//! # Multiple Method Handlers
//! Similar to the single method handler macro but takes one or more arguments for the HTTP methods
//! it should respond to. See [macro@route] macro docs.
//!
//! ```
//! # use actix_web::HttpResponse;
//! # use actix_web_codegen::route;
//! #[route("/test", method = "GET", method = "HEAD")]
//! async fn get_and_head_handler() -> HttpResponse {
//!     HttpResponse::Ok().finish()
//! }
//! ```
//!
//! # Multiple Path Handlers
//! There are no macros to generate multi-path handlers. Let us know in [this issue].
//!
//! [this issue]: https://github.com/actix/actix-web/issues/1709
//!
//! [actix-web attributes docs]: https://docs.rs/actix-web/latest/actix_web/#attributes
//! [GET]: macro@get
//! [POST]: macro@post
//! [PUT]: macro@put
//! [HEAD]: macro@head
//! [CONNECT]: macro@macro@connect
//! [OPTIONS]: macro@options
//! [TRACE]: macro@trace
//! [PATCH]: macro@patch
//! [DELETE]: macro@delete

#![recursion_limit = "512"]
#![deny(rust_2018_idioms, nonstandard_style)]
#![warn(future_incompatible)]

use proc_macro::TokenStream;
use quote::quote;

mod route;

/// Creates resource handler, allowing multiple HTTP method guards.
///
/// # Syntax
/// ```plain
/// #[route("path", method="HTTP_METHOD"[, attributes])]
/// ```
///
/// # Attributes
/// - `"path"`: Raw literal string with path for which to register handler.
/// - `name = "resource_name"`: Specifies resource name for the handler. If not set, the function
///   name of handler is used.
/// - `method = "HTTP_METHOD"`: Registers HTTP method to provide guard for. Upper-case string,
///   "GET", "POST" for example.
/// - `guard = "function_name"`: Registers function as guard using `actix_web::guard::fn_guard`.
/// - `wrap = "Middleware"`: Registers a resource middleware.
///
/// # Notes
/// Function name can be specified as any expression that is going to be accessible to the generate
/// code, e.g `my_guard` or `my_module::my_guard`.
///
/// # Examples
/// ```
/// # use actix_web::HttpResponse;
/// # use actix_web_codegen::route;
/// #[route("/test", method = "GET", method = "HEAD")]
/// async fn example() -> HttpResponse {
///     HttpResponse::Ok().finish()
/// }
/// ```
#[proc_macro_attribute]
pub fn route(args: TokenStream, input: TokenStream) -> TokenStream {
    route::with_method(None, args, input)
}

macro_rules! method_macro {
    ($variant:ident, $method:ident) => {
        #[doc = concat!("Creates route handler with `actix_web::guard::", stringify!($variant), "`.")]
        ///
        /// # Syntax
        /// ```plain
        #[doc = concat!("#[", stringify!($method), r#"("path"[, attributes])]"#)]
        /// ```
        ///
        /// # Attributes
        /// - `"path"`: Raw literal string with path for which to register handler.
        /// - `name = "resource_name"`: Specifies resource name for the handler. If not set, the
        ///   function name of handler is used.
        /// - `guard = "function_name"`: Registers function as guard.
        ///   using `actix_web::guard::fn_guard`.
        /// - `wrap = "Middleware"`: Registers a resource middleware.
        ///
        /// # Notes
        /// Function name can be specified as any expression that is going to be accessible to the generate
        /// code, e.g `my_guard` or `my_module::my_guard`.
        ///
        /// # Example
        /// ```
        /// # use actix_web::HttpResponse;
        #[doc = concat!("# use actix_web_codegen::", stringify!($method), ";")]
        #[doc = concat!("#[", stringify!($method), r#"("/")]"#)]
        /// async fn example() -> HttpResponse {
        ///     HttpResponse::Ok().finish()
        /// }
        /// ```
        #[proc_macro_attribute]
        pub fn $method(args: TokenStream, input: TokenStream) -> TokenStream {
            route::with_method(Some(route::MethodType::$variant), args, input)
        }
    };
}

method_macro!(Get, get);
method_macro!(Post, post);
method_macro!(Put, put);
method_macro!(Delete, delete);
method_macro!(Head, head);
method_macro!(Connect, connect);
method_macro!(Options, options);
method_macro!(Trace, trace);
method_macro!(Patch, patch);

/// Marks async main function as the Actix Web system entry-point.
///
/// # Examples
/// ```
/// #[actix_web::main]
/// async fn main() {
///     async { println!("Hello world"); }.await
/// }
/// ```
#[proc_macro_attribute]
pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
    let mut output: TokenStream = (quote! {
        #[::actix_web::rt::main(system = "::actix_web::rt::System")]
    })
    .into();

    output.extend(item);
    output
}

/// Marks async test functions to use the actix system entry-point.
///
/// # Examples
/// ```
/// #[actix_web::test]
/// async fn test() {
///     assert_eq!(async { "Hello world" }.await, "Hello world");
/// }
/// ```
#[proc_macro_attribute]
pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
    let mut output: TokenStream = (quote! {
        #[::actix_web::rt::test(system = "::actix_web::rt::System")]
    })
    .into();

    output.extend(item);
    output
}
<commit_msg>fmt codegen<commit_after>//! Routing and runtime macros for Actix Web.
//!
//! # Actix Web Re-exports
//! Actix Web re-exports a version of this crate in it's entirety so you usually don't have to
//! specify a dependency on this crate explicitly. Sometimes, however, updates are made to this
//! crate before the actix-web dependency is updated. Therefore, code examples here will show
//! explicit imports. Check the latest [actix-web attributes docs] to see which macros
//! are re-exported.
//!
//! # Runtime Setup
//! Used for setting up the actix async runtime. See [macro@main] macro docs.
//!
//! ```
//! #[actix_web_codegen::main] // or `#[actix_web::main]` in Actix Web apps
//! async fn main() {
//!     async { println!("Hello world"); }.await
//! }
//! ```
//!
//! # Single Method Handler
//! There is a macro to set up a handler for each of the most common HTTP methods that also define
//! additional guards and route-specific middleware.
//!
//! See docs for: [GET], [POST], [PATCH], [PUT], [DELETE], [HEAD], [CONNECT], [OPTIONS], [TRACE]
//!
//! ```
//! # use actix_web::HttpResponse;
//! # use actix_web_codegen::get;
//! #[get("/test")]
//! async fn get_handler() -> HttpResponse {
//!     HttpResponse::Ok().finish()
//! }
//! ```
//!
//! # Multiple Method Handlers
//! Similar to the single method handler macro but takes one or more arguments for the HTTP methods
//! it should respond to. See [macro@route] macro docs.
//!
//! ```
//! # use actix_web::HttpResponse;
//! # use actix_web_codegen::route;
//! #[route("/test", method = "GET", method = "HEAD")]
//! async fn get_and_head_handler() -> HttpResponse {
//!     HttpResponse::Ok().finish()
//! }
//! ```
//!
//! # Multiple Path Handlers
//! There are no macros to generate multi-path handlers. Let us know in [this issue].
//!
//! [this issue]: https://github.com/actix/actix-web/issues/1709
//!
//! [actix-web attributes docs]: https://docs.rs/actix-web/latest/actix_web/#attributes
//! [GET]: macro@get
//! [POST]: macro@post
//! [PUT]: macro@put
//! [HEAD]: macro@head
//! [CONNECT]: macro@macro@connect
//! [OPTIONS]: macro@options
//! [TRACE]: macro@trace
//! [PATCH]: macro@patch
//! [DELETE]: macro@delete

#![recursion_limit = "512"]
#![deny(rust_2018_idioms, nonstandard_style)]
#![warn(future_incompatible)]

use proc_macro::TokenStream;
use quote::quote;

mod route;

/// Creates resource handler, allowing multiple HTTP method guards.
///
/// # Syntax
/// ```plain
/// #[route("path", method="HTTP_METHOD"[, attributes])]
/// ```
///
/// # Attributes
/// - `"path"`: Raw literal string with path for which to register handler.
/// - `name = "resource_name"`: Specifies resource name for the handler. If not set, the function
///   name of handler is used.
/// - `method = "HTTP_METHOD"`: Registers HTTP method to provide guard for. Upper-case string,
///   "GET", "POST" for example.
/// - `guard = "function_name"`: Registers function as guard using `actix_web::guard::fn_guard`.
/// - `wrap = "Middleware"`: Registers a resource middleware.
///
/// # Notes
/// Function name can be specified as any expression that is going to be accessible to the generate
/// code, e.g `my_guard` or `my_module::my_guard`.
///
/// # Examples
/// ```
/// # use actix_web::HttpResponse;
/// # use actix_web_codegen::route;
/// #[route("/test", method = "GET", method = "HEAD")]
/// async fn example() -> HttpResponse {
///     HttpResponse::Ok().finish()
/// }
/// ```
#[proc_macro_attribute]
pub fn route(args: TokenStream, input: TokenStream) -> TokenStream {
    route::with_method(None, args, input)
}

macro_rules! method_macro {
    ($variant:ident, $method:ident) => {
#[doc = concat!("Creates route handler with `actix_web::guard::", stringify!($variant), "`.")]
///
/// # Syntax
/// ```plain
#[doc = concat!("#[", stringify!($method), r#"("path"[, attributes])]"#)]
/// ```
///
/// # Attributes
/// - `"path"`: Raw literal string with path for which to register handler.
/// - `name = "resource_name"`: Specifies resource name for the handler. If not set, the function
///   name of handler is used.
/// - `guard = "function_name"`: Registers function as guard using `actix_web::guard::fn_guard`.
/// - `wrap = "Middleware"`: Registers a resource middleware.
///
/// # Notes
/// Function name can be specified as any expression that is going to be accessible to the
/// generate code, e.g `my_guard` or `my_module::my_guard`.
///
/// # Example
/// ```
/// # use actix_web::HttpResponse;
#[doc = concat!("# use actix_web_codegen::", stringify!($method), ";")]
#[doc = concat!("#[", stringify!($method), r#"("/")]"#)]
/// async fn example() -> HttpResponse {
///     HttpResponse::Ok().finish()
/// }
/// ```
#[proc_macro_attribute]
pub fn $method(args: TokenStream, input: TokenStream) -> TokenStream {
    route::with_method(Some(route::MethodType::$variant), args, input)
}
    };
}

method_macro!(Get, get);
method_macro!(Post, post);
method_macro!(Put, put);
method_macro!(Delete, delete);
method_macro!(Head, head);
method_macro!(Connect, connect);
method_macro!(Options, options);
method_macro!(Trace, trace);
method_macro!(Patch, patch);

/// Marks async main function as the Actix Web system entry-point.
///
/// # Examples
/// ```
/// #[actix_web::main]
/// async fn main() {
///     async { println!("Hello world"); }.await
/// }
/// ```
#[proc_macro_attribute]
pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
    let mut output: TokenStream = (quote! {
        #[::actix_web::rt::main(system = "::actix_web::rt::System")]
    })
    .into();

    output.extend(item);
    output
}

/// Marks async test functions to use the actix system entry-point.
///
/// # Examples
/// ```
/// #[actix_web::test]
/// async fn test() {
///     assert_eq!(async { "Hello world" }.await, "Hello world");
/// }
/// ```
#[proc_macro_attribute]
pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
    let mut output: TokenStream = (quote! {
        #[::actix_web::rt::test(system = "::actix_web::rt::System")]
    })
    .into();

    output.extend(item);
    output
}
<|endoftext|>


<commit_before>use serde::Deserialize;
use std::io;
use std::path::Path;

use anyhow::{Context, Result};

use crate::utils::utils;

#[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct FallbackSettings {
    pub default_toolchain: Option<String>,
}

impl Default for FallbackSettings {
    fn default() -> Self {
        Self {
            default_toolchain: None,
        }
    }
}

impl FallbackSettings {
    pub(crate) fn new<P: AsRef<Path>>(path: P) -> Result<Option<Self>> {
        // Users cannot fix issues with missing/unreadable/invalid centralised files, but logging isn't setup early so
        // we can't simply trap all errors and log diagnostics. Ideally we would, and then separate these into different
        // sorts of issues, logging messages about errors that should be fixed. Instead we trap some conservative errors
        // that hopefully won't lead to too many tickets.
        match utils::read_file("fallback settings", path.as_ref()) {
            Err(e) => match e.downcast_ref::<io::Error>() {
                Some(io_err) => match io_err.kind() {
                    io::ErrorKind::NotFound | io::ErrorKind::PermissionDenied => Ok(None),
                    _ => Err(e),
                },
                None => Err(e),
            },
            Ok(file_contents) => Ok(Some(
                toml::from_str(&file_contents).context("error parsing settings")?,
            )),
        }
    }
}
<commit_msg>derive default for FallbackSettings<commit_after>use serde::Deserialize;
use std::io;
use std::path::Path;

use anyhow::{Context, Result};

use crate::utils::utils;

#[derive(Clone, Debug, Deserialize, PartialEq, Default)]
pub struct FallbackSettings {
    pub default_toolchain: Option<String>,
}

impl FallbackSettings {
    pub(crate) fn new<P: AsRef<Path>>(path: P) -> Result<Option<Self>> {
        // Users cannot fix issues with missing/unreadable/invalid centralised files, but logging isn't setup early so
        // we can't simply trap all errors and log diagnostics. Ideally we would, and then separate these into different
        // sorts of issues, logging messages about errors that should be fixed. Instead we trap some conservative errors
        // that hopefully won't lead to too many tickets.
        match utils::read_file("fallback settings", path.as_ref()) {
            Err(e) => match e.downcast_ref::<io::Error>() {
                Some(io_err) => match io_err.kind() {
                    io::ErrorKind::NotFound | io::ErrorKind::PermissionDenied => Ok(None),
                    _ => Err(e),
                },
                None => Err(e),
            },
            Ok(file_contents) => Ok(Some(
                toml::from_str(&file_contents).context("error parsing settings")?,
            )),
        }
    }
}
<|endoftext|>


<commit_before>//! This module provides a generic iterator and traits for mapping from an
//! index to a topology from some shape.

use std::ops::Range;

use super::topology::Polygonal;

pub struct Generate<'a, G, P>
where
    G: 'a,
{
    generator: &'a G,
    range: Range<usize>,
    f: fn(&'a G, usize) -> P,
}

impl<'a, G, P> Generate<'a, G, P>
where
    G: 'a,
{
    pub(super) fn new(generator: &'a G, range: Range<usize>, f: fn(&'a G, usize) -> P) -> Self {
        Generate {
            generator: generator,
            range: range,
            f: f,
        }
    }
}

impl<'a, G, P> Iterator for Generate<'a, G, P>
where
    G: 'a,
{
    type Item = P;

    fn next(&mut self) -> Option<Self::Item> {
        self.range
            .next()
            .map(|index| (self.f)(self.generator, index))
    }
}

pub trait VertexGenerator {
    fn vertex_count(&self) -> usize;
}

pub trait SpatialVertexGenerator: VertexGenerator {
    type Output;

    fn spatial_vertex(&self, index: usize) -> Self::Output;
}

pub trait SpatialVertices<P>: Sized {
    fn spatial_vertices(&self) -> Generate<Self, P>;
}

impl<G, P> SpatialVertices<P> for G
where
    G: SpatialVertexGenerator<Output = P>,
{
    fn spatial_vertices(&self) -> Generate<Self, P> {
        Generate::new(self, 0..self.vertex_count(), G::spatial_vertex)
    }
}

pub trait PolygonGenerator {
    fn polygon_count(&self) -> usize;
}

pub trait SpatialPolygonGenerator: PolygonGenerator {
    type Output: Polygonal;

    fn spatial_polygon(&self, index: usize) -> Self::Output;
}

pub trait SpatialPolygons<P>: Sized {
    fn spatial_polygons(&self) -> Generate<Self, P>;
}

impl<G, P> SpatialPolygons<P> for G
where
    G: SpatialPolygonGenerator<Output = P>,
    P: Polygonal,
{
    fn spatial_polygons(&self) -> Generate<Self, P> {
        Generate::new(self, 0..self.polygon_count(), G::spatial_polygon)
    }
}

pub trait IndexedPolygonGenerator: VertexGenerator + PolygonGenerator {
    type Output: Polygonal;

    fn indexed_polygon(&self, index: usize) -> <Self as IndexedPolygonGenerator>::Output;
}

pub trait IndexedPolygons<P>: Sized {
    fn indexed_polygons(&self) -> Generate<Self, P>;
}

impl<G, P> IndexedPolygons<P> for G
where
    G: IndexedPolygonGenerator<Output = P> + VertexGenerator + PolygonGenerator,
    P: Polygonal,
{
    fn indexed_polygons(&self) -> Generate<Self, P> {
        Generate::new(self, 0..self.polygon_count(), G::indexed_polygon)
    }
}

pub trait TexturedPolygonGenerator: PolygonGenerator {
    type Output: Polygonal;

    fn textured_polygon(&self, index: usize) -> <Self as TexturedPolygonGenerator>::Output;
}

pub trait TexturedPolygons<P>: Sized {
    fn textured_polygons(&self) -> Generate<Self, P>;
}

impl<G, P> TexturedPolygons<P> for G
where
    G: PolygonGenerator + TexturedPolygonGenerator<Output = P>,
    P: Polygonal,
{
    fn textured_polygons(&self) -> Generate<Self, P> {
        Generate::new(self, 0..self.polygon_count(), G::textured_polygon)
    }
}
<commit_msg>Use consistent intra-crate imports.<commit_after>//! This module provides a generic iterator and traits for mapping from an
//! index to a topology from some shape.

use std::ops::Range;

use generate::topology::Polygonal;

pub struct Generate<'a, G, P>
where
    G: 'a,
{
    generator: &'a G,
    range: Range<usize>,
    f: fn(&'a G, usize) -> P,
}

impl<'a, G, P> Generate<'a, G, P>
where
    G: 'a,
{
    pub(super) fn new(generator: &'a G, range: Range<usize>, f: fn(&'a G, usize) -> P) -> Self {
        Generate {
            generator: generator,
            range: range,
            f: f,
        }
    }
}

impl<'a, G, P> Iterator for Generate<'a, G, P>
where
    G: 'a,
{
    type Item = P;

    fn next(&mut self) -> Option<Self::Item> {
        self.range
            .next()
            .map(|index| (self.f)(self.generator, index))
    }
}

pub trait VertexGenerator {
    fn vertex_count(&self) -> usize;
}

pub trait SpatialVertexGenerator: VertexGenerator {
    type Output;

    fn spatial_vertex(&self, index: usize) -> Self::Output;
}

pub trait SpatialVertices<P>: Sized {
    fn spatial_vertices(&self) -> Generate<Self, P>;
}

impl<G, P> SpatialVertices<P> for G
where
    G: SpatialVertexGenerator<Output = P>,
{
    fn spatial_vertices(&self) -> Generate<Self, P> {
        Generate::new(self, 0..self.vertex_count(), G::spatial_vertex)
    }
}

pub trait PolygonGenerator {
    fn polygon_count(&self) -> usize;
}

pub trait SpatialPolygonGenerator: PolygonGenerator {
    type Output: Polygonal;

    fn spatial_polygon(&self, index: usize) -> Self::Output;
}

pub trait SpatialPolygons<P>: Sized {
    fn spatial_polygons(&self) -> Generate<Self, P>;
}

impl<G, P> SpatialPolygons<P> for G
where
    G: SpatialPolygonGenerator<Output = P>,
    P: Polygonal,
{
    fn spatial_polygons(&self) -> Generate<Self, P> {
        Generate::new(self, 0..self.polygon_count(), G::spatial_polygon)
    }
}

pub trait IndexedPolygonGenerator: VertexGenerator + PolygonGenerator {
    type Output: Polygonal;

    fn indexed_polygon(&self, index: usize) -> <Self as IndexedPolygonGenerator>::Output;
}

pub trait IndexedPolygons<P>: Sized {
    fn indexed_polygons(&self) -> Generate<Self, P>;
}

impl<G, P> IndexedPolygons<P> for G
where
    G: IndexedPolygonGenerator<Output = P> + VertexGenerator + PolygonGenerator,
    P: Polygonal,
{
    fn indexed_polygons(&self) -> Generate<Self, P> {
        Generate::new(self, 0..self.polygon_count(), G::indexed_polygon)
    }
}

pub trait TexturedPolygonGenerator: PolygonGenerator {
    type Output: Polygonal;

    fn textured_polygon(&self, index: usize) -> <Self as TexturedPolygonGenerator>::Output;
}

pub trait TexturedPolygons<P>: Sized {
    fn textured_polygons(&self) -> Generate<Self, P>;
}

impl<G, P> TexturedPolygons<P> for G
where
    G: PolygonGenerator + TexturedPolygonGenerator<Output = P>,
    P: Polygonal,
{
    fn textured_polygons(&self) -> Generate<Self, P> {
        Generate::new(self, 0..self.polygon_count(), G::textured_polygon)
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
// Copyright 2013 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The normal and derived distributions.

use crate::utils::ziggurat;
use num_traits::Float;
use crate::{ziggurat_tables, Distribution, Open01};
use rand::Rng;
use core::fmt;

/// Samples floating-point numbers according to the normal distribution
/// `N(0, 1)` (a.k.a. a standard normal, or Gaussian). This is equivalent to
/// `Normal::new(0.0, 1.0)` but faster.
///
/// See `Normal` for the general normal distribution.
///
/// Implemented via the ZIGNOR variant[^1] of the Ziggurat method.
///
/// [^1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to
///       Generate Normal Random Samples*](
///       https://www.doornik.com/research/ziggurat.pdf).
///       Nuffield College, Oxford
///
/// # Example
/// ```
/// use rand::prelude::*;
/// use rand_distr::StandardNormal;
///
/// let val: f64 = thread_rng().sample(StandardNormal);
/// println!("{}", val);
/// ```
#[derive(Clone, Copy, Debug)]
pub struct StandardNormal;

impl Distribution<f32> for StandardNormal {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f32 {
        // TODO: use optimal 32-bit implementation
        let x: f64 = self.sample(rng);
        x as f32
    }
}

impl Distribution<f64> for StandardNormal {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        #[inline]
        fn pdf(x: f64) -> f64 {
            (-x * x / 2.0).exp()
        }
        #[inline]
        fn zero_case<R: Rng + ?Sized>(rng: &mut R, u: f64) -> f64 {
            // compute a random number in the tail by hand

            // strange initial conditions, because the loop is not
            // do-while, so the condition should be true on the first
            // run, they get overwritten anyway (0 < 1, so these are
            // good).
            let mut x = 1.0f64;
            let mut y = 0.0f64;

            while -2.0 * y < x * x {
                let x_: f64 = rng.sample(Open01);
                let y_: f64 = rng.sample(Open01);

                x = x_.ln() / ziggurat_tables::ZIG_NORM_R;
                y = y_.ln();
            }

            if u < 0.0 {
                x - ziggurat_tables::ZIG_NORM_R
            } else {
                ziggurat_tables::ZIG_NORM_R - x
            }
        }

        ziggurat(
            rng,
            true, // this is symmetric
            &ziggurat_tables::ZIG_NORM_X,
            &ziggurat_tables::ZIG_NORM_F,
            pdf,
            zero_case,
        )
    }
}

/// The normal distribution `N(mean, std_dev**2)`.
///
/// This uses the ZIGNOR variant of the Ziggurat method, see [`StandardNormal`]
/// for more details.
///
/// Note that [`StandardNormal`] is an optimised implementation for mean 0, and
/// standard deviation 1.
///
/// # Example
///
/// ```
/// use rand_distr::{Normal, Distribution};
///
/// // mean 2, standard deviation 3
/// let normal = Normal::new(2.0, 3.0).unwrap();
/// let v = normal.sample(&mut rand::thread_rng());
/// println!("{} is from a N(2, 9) distribution", v)
/// ```
///
/// [`StandardNormal`]: crate::StandardNormal
#[derive(Clone, Copy, Debug)]
pub struct Normal<F>
where F: Float, StandardNormal: Distribution<F>
{
    mean: F,
    std_dev: F,
}

/// Error type returned from `Normal::new` and `LogNormal::new`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Error {
    /// The mean value is too small (log-normal samples must be positive)
    MeanTooSmall,
    /// The standard deviation or other dispersion parameter is negative,
    /// infinite, or not-a-number.
    BadVariance,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            Error::MeanTooSmall => "mean < 0 or NaN in log-normal distribution",
            Error::BadVariance => "variation parameter is negative or non-finite in (log)normal distribution",
        })
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}

impl<F> Normal<F>
where F: Float, StandardNormal: Distribution<F>
{
    /// Construct, from mean and standard deviation
    ///
    /// Parameters:
    ///
    /// -   mean (`μ`, unrestricted)
    /// -   standard deviation (`σ`, must be finite)
    #[inline]
    pub fn new(mean: F, std_dev: F) -> Result<Normal<F>, Error> {
        if !std_dev.is_finite() {
            return Err(Error::BadVariance);
        }
        Ok(Normal { mean, std_dev })
    }

    /// Construct, from mean and coefficient of variation
    ///
    /// Parameters:
    ///
    /// -   mean (`μ`, unrestricted)
    /// -   coefficient of variation (`cv = abs(σ / μ)`)
    #[inline]
    pub fn from_mean_cv(mean: F, cv: F) -> Result<Normal<F>, Error> {
        if !cv.is_finite() || cv < F::zero() {
            return Err(Error::BadVariance);
        }
        let std_dev = cv * mean;
        Ok(Normal { mean, std_dev })
    }

    /// Sample from a z-score
    ///
    /// This may be useful for generating correlated samples `x1` and `x2`
    /// from two different distributions, as follows.
    /// ```
    /// # use rand::prelude::*;
    /// # use rand_distr::{Normal, StandardNormal};
    /// let mut rng = thread_rng();
    /// let z = StandardNormal.sample(&mut rng);
    /// let x1 = Normal::new(0.0, 1.0).unwrap().from_zscore(z);
    /// let x2 = Normal::new(2.0, -3.0).unwrap().from_zscore(z);
    /// ```
    #[inline]
    pub fn from_zscore(&self, zscore: F) -> F {
        self.mean + self.std_dev * zscore
    }
}

impl<F> Distribution<F> for Normal<F>
where F: Float, StandardNormal: Distribution<F>
{
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> F {
        self.from_zscore(rng.sample(StandardNormal))
    }
}

/// The log-normal distribution `ln N(mean, std_dev**2)`.
///
/// If `X` is log-normal distributed, then `ln(X)` is `N(mean, std_dev**2)`
/// distributed.
///
/// # Example
///
/// ```
/// use rand_distr::{LogNormal, Distribution};
///
/// // mean 2, standard deviation 3
/// let log_normal = LogNormal::new(2.0, 3.0).unwrap();
/// let v = log_normal.sample(&mut rand::thread_rng());
/// println!("{} is from an ln N(2, 9) distribution", v)
/// ```
#[derive(Clone, Copy, Debug)]
pub struct LogNormal<F>
where F: Float, StandardNormal: Distribution<F>
{
    norm: Normal<F>,
}

impl<F> LogNormal<F>
where F: Float, StandardNormal: Distribution<F>
{
    /// Construct, from (log-space) mean and standard deviation
    ///
    /// Parameters are the "standard" log-space measures (these are the mean
    /// and standard deviation of the logarithm of samples):
    ///
    /// -   `mu` (`μ`, unrestricted) is the mean of the underlying distribution
    /// -   `sigma` (`σ`, must be finite) is the standard deviation of the
    ///     underlying Normal distribution
    #[inline]
    pub fn new(mu: F, sigma: F) -> Result<LogNormal<F>, Error> {
        let norm = Normal::new(mu, sigma)?;
        Ok(LogNormal { norm })
    }

    /// Construct, from (linear-space) mean and coefficient of variation
    ///
    /// Parameters are linear-space measures:
    ///
    /// -   mean (`μ > 0`) is the (real) mean of the distribution
    /// -   coefficient of variation (`cv = σ / μ`, requiring `cv ≥ 0`) is a
    ///     standardized measure of dispersion
    ///
    /// As a special exception, `μ = 0, cv = 0` is allowed (samples are `-inf`).
    #[inline]
    pub fn from_mean_cv(mean: F, cv: F) -> Result<LogNormal<F>, Error> {
        if cv == F::zero() {
            let mu = mean.ln();
            let norm = Normal::new(mu, F::zero()).unwrap();
            return Ok(LogNormal { norm });
        }
        if !(mean > F::zero()) {
            return Err(Error::MeanTooSmall);
        }
        if !(cv >= F::zero()) {
            return Err(Error::BadVariance);
        }

        // Using X ~ lognormal(μ, σ), CV² = Var(X) / E(X)²
        // E(X) = exp(μ + σ² / 2) = exp(μ) × exp(σ² / 2)
        // Var(X) = exp(2μ + σ²)(exp(σ²) - 1) = E(X)² × (exp(σ²) - 1)
        // but Var(X) = (CV × E(X))² so CV² = exp(σ²) - 1
        // thus σ² = log(CV² + 1)
        // and exp(μ) = E(X) / exp(σ² / 2) = E(X) / sqrt(CV² + 1)
        let a = F::one() + cv * cv; // e
        let mu = F::from(0.5).unwrap() * (mean * mean / a).ln();
        let sigma = a.ln().sqrt();
        let norm = Normal::new(mu, sigma)?;
        Ok(LogNormal { norm })
    }

    /// Sample from a z-score
    ///
    /// This may be useful for generating correlated samples, as follows.
    /// ```
    /// # use rand::prelude::*;
    /// # use rand_distr::{LogNormal, StandardNormal};
    /// let mut rng = thread_rng();
    /// let z = StandardNormal.sample(&mut rng);
    /// let x1 = LogNormal::from_mean_cv(3.0, 1.0).unwrap().from_zscore(z);
    /// let x2 = LogNormal::from_mean_cv(2.0, 1.0).unwrap().from_zscore(z);
    /// ```
    #[inline]
    pub fn from_zscore(&self, zscore: F) -> F {
        self.norm.from_zscore(zscore).exp()
    }
}

impl<F> Distribution<F> for LogNormal<F>
where F: Float, StandardNormal: Distribution<F>
{
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> F {
        self.norm.sample(rng).exp()
    }
}

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

    #[test]
    fn test_normal() {
        let norm = Normal::new(10.0, 10.0).unwrap();
        let mut rng = crate::test::rng(210);
        for _ in 0..1000 {
            norm.sample(&mut rng);
        }
    }
    #[test]
    fn test_normal_cv() {
        let norm = Normal::from_mean_cv(1024.0, 1.0 / 256.0).unwrap();
        assert_eq!((norm.mean, norm.std_dev), (1024.0, 4.0));
    }
    #[test]
    fn test_normal_invalid_sd() {
        assert!(Normal::from_mean_cv(10.0, -1.0).is_err());
    }

    #[test]
    fn test_log_normal() {
        let lnorm = LogNormal::new(10.0, 10.0).unwrap();
        let mut rng = crate::test::rng(211);
        for _ in 0..1000 {
            lnorm.sample(&mut rng);
        }
    }
    #[test]
    fn test_log_normal_cv() {
        let lnorm = LogNormal::from_mean_cv(0.0, 0.0).unwrap();
        assert_eq!((lnorm.norm.mean, lnorm.norm.std_dev), (-std::f64::INFINITY, 0.0));

        let lnorm = LogNormal::from_mean_cv(1.0, 0.0).unwrap();
        assert_eq!((lnorm.norm.mean, lnorm.norm.std_dev), (0.0, 0.0));

        let e = std::f64::consts::E;
        let lnorm = LogNormal::from_mean_cv(e.sqrt(), (e - 1.0).sqrt()).unwrap();
        assert_almost_eq!(lnorm.norm.mean, 0.0, 2e-16);
        assert_almost_eq!(lnorm.norm.std_dev, 1.0, 2e-16);

        let lnorm = LogNormal::from_mean_cv(e.powf(1.5), (e - 1.0).sqrt()).unwrap();
        assert_eq!((lnorm.norm.mean, lnorm.norm.std_dev), (1.0, 1.0));
    }
    #[test]
    fn test_log_normal_invalid_sd() {
        assert!(LogNormal::from_mean_cv(-1.0, 1.0).is_err());
        assert!(LogNormal::from_mean_cv(0.0, 1.0).is_err());
        assert!(LogNormal::from_mean_cv(1.0, -1.0).is_err());
    }
}
<commit_msg>Update correlated log-normal samples example<commit_after>// Copyright 2018 Developers of the Rand project.
// Copyright 2013 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The normal and derived distributions.

use crate::utils::ziggurat;
use num_traits::Float;
use crate::{ziggurat_tables, Distribution, Open01};
use rand::Rng;
use core::fmt;

/// Samples floating-point numbers according to the normal distribution
/// `N(0, 1)` (a.k.a. a standard normal, or Gaussian). This is equivalent to
/// `Normal::new(0.0, 1.0)` but faster.
///
/// See `Normal` for the general normal distribution.
///
/// Implemented via the ZIGNOR variant[^1] of the Ziggurat method.
///
/// [^1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to
///       Generate Normal Random Samples*](
///       https://www.doornik.com/research/ziggurat.pdf).
///       Nuffield College, Oxford
///
/// # Example
/// ```
/// use rand::prelude::*;
/// use rand_distr::StandardNormal;
///
/// let val: f64 = thread_rng().sample(StandardNormal);
/// println!("{}", val);
/// ```
#[derive(Clone, Copy, Debug)]
pub struct StandardNormal;

impl Distribution<f32> for StandardNormal {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f32 {
        // TODO: use optimal 32-bit implementation
        let x: f64 = self.sample(rng);
        x as f32
    }
}

impl Distribution<f64> for StandardNormal {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        #[inline]
        fn pdf(x: f64) -> f64 {
            (-x * x / 2.0).exp()
        }
        #[inline]
        fn zero_case<R: Rng + ?Sized>(rng: &mut R, u: f64) -> f64 {
            // compute a random number in the tail by hand

            // strange initial conditions, because the loop is not
            // do-while, so the condition should be true on the first
            // run, they get overwritten anyway (0 < 1, so these are
            // good).
            let mut x = 1.0f64;
            let mut y = 0.0f64;

            while -2.0 * y < x * x {
                let x_: f64 = rng.sample(Open01);
                let y_: f64 = rng.sample(Open01);

                x = x_.ln() / ziggurat_tables::ZIG_NORM_R;
                y = y_.ln();
            }

            if u < 0.0 {
                x - ziggurat_tables::ZIG_NORM_R
            } else {
                ziggurat_tables::ZIG_NORM_R - x
            }
        }

        ziggurat(
            rng,
            true, // this is symmetric
            &ziggurat_tables::ZIG_NORM_X,
            &ziggurat_tables::ZIG_NORM_F,
            pdf,
            zero_case,
        )
    }
}

/// The normal distribution `N(mean, std_dev**2)`.
///
/// This uses the ZIGNOR variant of the Ziggurat method, see [`StandardNormal`]
/// for more details.
///
/// Note that [`StandardNormal`] is an optimised implementation for mean 0, and
/// standard deviation 1.
///
/// # Example
///
/// ```
/// use rand_distr::{Normal, Distribution};
///
/// // mean 2, standard deviation 3
/// let normal = Normal::new(2.0, 3.0).unwrap();
/// let v = normal.sample(&mut rand::thread_rng());
/// println!("{} is from a N(2, 9) distribution", v)
/// ```
///
/// [`StandardNormal`]: crate::StandardNormal
#[derive(Clone, Copy, Debug)]
pub struct Normal<F>
where F: Float, StandardNormal: Distribution<F>
{
    mean: F,
    std_dev: F,
}

/// Error type returned from `Normal::new` and `LogNormal::new`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Error {
    /// The mean value is too small (log-normal samples must be positive)
    MeanTooSmall,
    /// The standard deviation or other dispersion parameter is negative,
    /// infinite, or not-a-number.
    BadVariance,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            Error::MeanTooSmall => "mean < 0 or NaN in log-normal distribution",
            Error::BadVariance => "variation parameter is negative or non-finite in (log)normal distribution",
        })
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}

impl<F> Normal<F>
where F: Float, StandardNormal: Distribution<F>
{
    /// Construct, from mean and standard deviation
    ///
    /// Parameters:
    ///
    /// -   mean (`μ`, unrestricted)
    /// -   standard deviation (`σ`, must be finite)
    #[inline]
    pub fn new(mean: F, std_dev: F) -> Result<Normal<F>, Error> {
        if !std_dev.is_finite() {
            return Err(Error::BadVariance);
        }
        Ok(Normal { mean, std_dev })
    }

    /// Construct, from mean and coefficient of variation
    ///
    /// Parameters:
    ///
    /// -   mean (`μ`, unrestricted)
    /// -   coefficient of variation (`cv = abs(σ / μ)`)
    #[inline]
    pub fn from_mean_cv(mean: F, cv: F) -> Result<Normal<F>, Error> {
        if !cv.is_finite() || cv < F::zero() {
            return Err(Error::BadVariance);
        }
        let std_dev = cv * mean;
        Ok(Normal { mean, std_dev })
    }

    /// Sample from a z-score
    ///
    /// This may be useful for generating correlated samples `x1` and `x2`
    /// from two different distributions, as follows.
    /// ```
    /// # use rand::prelude::*;
    /// # use rand_distr::{Normal, StandardNormal};
    /// let mut rng = thread_rng();
    /// let z = StandardNormal.sample(&mut rng);
    /// let x1 = Normal::new(0.0, 1.0).unwrap().from_zscore(z);
    /// let x2 = Normal::new(2.0, -3.0).unwrap().from_zscore(z);
    /// ```
    #[inline]
    pub fn from_zscore(&self, zscore: F) -> F {
        self.mean + self.std_dev * zscore
    }
}

impl<F> Distribution<F> for Normal<F>
where F: Float, StandardNormal: Distribution<F>
{
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> F {
        self.from_zscore(rng.sample(StandardNormal))
    }
}

/// The log-normal distribution `ln N(mean, std_dev**2)`.
///
/// If `X` is log-normal distributed, then `ln(X)` is `N(mean, std_dev**2)`
/// distributed.
///
/// # Example
///
/// ```
/// use rand_distr::{LogNormal, Distribution};
///
/// // mean 2, standard deviation 3
/// let log_normal = LogNormal::new(2.0, 3.0).unwrap();
/// let v = log_normal.sample(&mut rand::thread_rng());
/// println!("{} is from an ln N(2, 9) distribution", v)
/// ```
#[derive(Clone, Copy, Debug)]
pub struct LogNormal<F>
where F: Float, StandardNormal: Distribution<F>
{
    norm: Normal<F>,
}

impl<F> LogNormal<F>
where F: Float, StandardNormal: Distribution<F>
{
    /// Construct, from (log-space) mean and standard deviation
    ///
    /// Parameters are the "standard" log-space measures (these are the mean
    /// and standard deviation of the logarithm of samples):
    ///
    /// -   `mu` (`μ`, unrestricted) is the mean of the underlying distribution
    /// -   `sigma` (`σ`, must be finite) is the standard deviation of the
    ///     underlying Normal distribution
    #[inline]
    pub fn new(mu: F, sigma: F) -> Result<LogNormal<F>, Error> {
        let norm = Normal::new(mu, sigma)?;
        Ok(LogNormal { norm })
    }

    /// Construct, from (linear-space) mean and coefficient of variation
    ///
    /// Parameters are linear-space measures:
    ///
    /// -   mean (`μ > 0`) is the (real) mean of the distribution
    /// -   coefficient of variation (`cv = σ / μ`, requiring `cv ≥ 0`) is a
    ///     standardized measure of dispersion
    ///
    /// As a special exception, `μ = 0, cv = 0` is allowed (samples are `-inf`).
    #[inline]
    pub fn from_mean_cv(mean: F, cv: F) -> Result<LogNormal<F>, Error> {
        if cv == F::zero() {
            let mu = mean.ln();
            let norm = Normal::new(mu, F::zero()).unwrap();
            return Ok(LogNormal { norm });
        }
        if !(mean > F::zero()) {
            return Err(Error::MeanTooSmall);
        }
        if !(cv >= F::zero()) {
            return Err(Error::BadVariance);
        }

        // Using X ~ lognormal(μ, σ), CV² = Var(X) / E(X)²
        // E(X) = exp(μ + σ² / 2) = exp(μ) × exp(σ² / 2)
        // Var(X) = exp(2μ + σ²)(exp(σ²) - 1) = E(X)² × (exp(σ²) - 1)
        // but Var(X) = (CV × E(X))² so CV² = exp(σ²) - 1
        // thus σ² = log(CV² + 1)
        // and exp(μ) = E(X) / exp(σ² / 2) = E(X) / sqrt(CV² + 1)
        let a = F::one() + cv * cv; // e
        let mu = F::from(0.5).unwrap() * (mean * mean / a).ln();
        let sigma = a.ln().sqrt();
        let norm = Normal::new(mu, sigma)?;
        Ok(LogNormal { norm })
    }

    /// Sample from a z-score
    ///
    /// This may be useful for generating correlated samples `x1` and `x2`
    /// from two different distributions, as follows.
    /// ```
    /// # use rand::prelude::*;
    /// # use rand_distr::{LogNormal, StandardNormal};
    /// let mut rng = thread_rng();
    /// let z = StandardNormal.sample(&mut rng);
    /// let x1 = LogNormal::from_mean_cv(3.0, 1.0).unwrap().from_zscore(z);
    /// let x2 = LogNormal::from_mean_cv(2.0, 4.0).unwrap().from_zscore(z);
    /// ```
    #[inline]
    pub fn from_zscore(&self, zscore: F) -> F {
        self.norm.from_zscore(zscore).exp()
    }
}

impl<F> Distribution<F> for LogNormal<F>
where F: Float, StandardNormal: Distribution<F>
{
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> F {
        self.norm.sample(rng).exp()
    }
}

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

    #[test]
    fn test_normal() {
        let norm = Normal::new(10.0, 10.0).unwrap();
        let mut rng = crate::test::rng(210);
        for _ in 0..1000 {
            norm.sample(&mut rng);
        }
    }
    #[test]
    fn test_normal_cv() {
        let norm = Normal::from_mean_cv(1024.0, 1.0 / 256.0).unwrap();
        assert_eq!((norm.mean, norm.std_dev), (1024.0, 4.0));
    }
    #[test]
    fn test_normal_invalid_sd() {
        assert!(Normal::from_mean_cv(10.0, -1.0).is_err());
    }

    #[test]
    fn test_log_normal() {
        let lnorm = LogNormal::new(10.0, 10.0).unwrap();
        let mut rng = crate::test::rng(211);
        for _ in 0..1000 {
            lnorm.sample(&mut rng);
        }
    }
    #[test]
    fn test_log_normal_cv() {
        let lnorm = LogNormal::from_mean_cv(0.0, 0.0).unwrap();
        assert_eq!((lnorm.norm.mean, lnorm.norm.std_dev), (-std::f64::INFINITY, 0.0));

        let lnorm = LogNormal::from_mean_cv(1.0, 0.0).unwrap();
        assert_eq!((lnorm.norm.mean, lnorm.norm.std_dev), (0.0, 0.0));

        let e = std::f64::consts::E;
        let lnorm = LogNormal::from_mean_cv(e.sqrt(), (e - 1.0).sqrt()).unwrap();
        assert_almost_eq!(lnorm.norm.mean, 0.0, 2e-16);
        assert_almost_eq!(lnorm.norm.std_dev, 1.0, 2e-16);

        let lnorm = LogNormal::from_mean_cv(e.powf(1.5), (e - 1.0).sqrt()).unwrap();
        assert_eq!((lnorm.norm.mean, lnorm.norm.std_dev), (1.0, 1.0));
    }
    #[test]
    fn test_log_normal_invalid_sd() {
        assert!(LogNormal::from_mean_cv(-1.0, 1.0).is_err());
        assert!(LogNormal::from_mean_cv(0.0, 1.0).is_err());
        assert!(LogNormal::from_mean_cv(1.0, -1.0).is_err());
    }
}
<|endoftext|>


<commit_before>use Widget;
use CTX;
use std::str;
//use std::from_str::FromStr;

///a Widget used for monochrom vektor Icons.
pub struct Icon<'a>{
    path: &'a str,//a path like in svg
    pub fill: Option<(f64,f64,f64)>,
    color: (f64, f64, f64),
}

impl<'a> Icon<'a>{
    ///create a new icon form a given svg-path
    pub fn new(path: &'a str, color: (f64,f64,f64)) -> Icon<'a>{
        Icon{
            path: path,
            color: color,
            fill: None,
        }
    }
}

//internal struct to parse a svg-path
struct PathParser<'a>{
    chars: str::Chars<'a>,
    last: Option<char>,//last character to unread
    unread: bool,
}

impl<'a> PathParser<'a>{
    fn new(c: str::Chars<'a>) -> PathParser<'a>{
        PathParser{
            chars: c,
            last: None,
            unread: false,
        }
    }
    #[inline]
    fn next(&mut self) -> Option<char>{
        if self.unread{
            self.unread = false;
            self.last
        }else{
            self.last = self.chars.next();
            self.last
        }
    }
    #[inline]
    fn unread(&mut self){
        self.unread = true;
    }

    #[inline]
    fn skip_space(&mut self){
        loop{
            match self.next(){
                None => break,
                Some(c) => if !((c == ' ') | (c == ',')){
                    break;
                }
            }
        }
        self.unread();
    }

    #[inline]
    fn num(&mut self) -> Option<f64>{//closure to read from stream
        let mut b = String::new();
        self.skip_space();
        let mut cc = match self.next(){
            Some(e) => e,
            None => return None
        };
        if cc == '-'{//handle minus
            b.push(cc);
            cc = match self.next(){
                Some(e) => e,
                None => return None
            };
        }
        let mut nf = true;
        while cc.is_digit(10)|((cc == '.')&&nf){
            //println!("    {}", cc);
            if cc == '.'{
                nf = false;
            }
            b.push(cc);
            cc = match self.next(){
                Some(e) => e,
                None => return None
            };
        }
        self.unread();
        //println!("    {}", cc);
        //println!("num {}", b);
        from_str::<f64>(b.as_slice())
    }
}

impl<'a> Widget<()> for Icon<'a>{
    ///this function will render a svg path, if the path is not correct it will panic
    fn render(&mut self, ctx: &mut CTX<()>) -> (f64, f64) {
        ctx.draw(|c|{
            //Parsing and drawing logic
            //TODO: add this
            let (r,g,b) = self.color;
            let mut before: Option<(f64,f64)> = None;//for s path
            c.set_source_rgb(r, g, b);
            let mut chars = PathParser::new(self.path.chars());

            loop{
                //TODO: make multible comands work
                let cc = match chars.next(){
                    Some(e) => e,
                    None => break
                };
                match cc{
                    'M' => {//move to
                        let x = chars.num().unwrap();
                        let y = chars.num().unwrap();
                        c.move_to(x,y);
                        //println!("move to ({} {})", x, y);
                        before = None;
                    },
                    'm' => {//move to
                        let x = chars.num().unwrap();
                        let y = chars.num().unwrap();
                        c.rel_move_to(x,y);
                        before = None;
                    },
                    'L' => {//line to
                        loop{//loop over the numbers
                            let x = match chars.num(){
                                Some(s) => s,
                                None => break
                            };
                            let y = chars.num().unwrap();
                            c.line_to(x,y);
                            //println!("line to ({} {})",x,y);
                        }
                        before = None;
                    },
                    'l' => {//line to
                        //println!("line to relative");
                        loop{//loop over the numbers
                            let x = match chars.num(){
                                Some(s) => s,
                                None => break
                            };
                            let y = chars.num().unwrap();
                            c.rel_line_to(x,y);
                            //println!("line to ({} {})",x,y);
                        }
                        before = None;
                    },
                    'V' => {//vertical line
                        //println!("vertival line");
                        c.line_to(0.0,chars.num().unwrap());
                        before = None;
                    },
                    'v' => {//vertical line
                        //println!("vertival line relative");
                        c.rel_line_to(0.0,chars.num().unwrap());
                        before = None;
                    },
                    'H' => {//horizontal line
                        c.line_to(chars.num().unwrap(),0.0);
                        before = None;
                        //println!("horizontal line");
                    },
                    'h' => {//horizontal line
                        before = None;
                        c.rel_line_to(chars.num().unwrap(),0.0);
                        //println!("horizontal line relative");
                    },
                    'Z' | 'z' => {//close path
                        //println!("close path");
                        before = None;
                        c.close_path();
                    },
                    'c' => {//relative curve
                        loop{//loop over the numbers
                            let x1 = match chars.num(){
                                Some(s) => s,
                                None => break
                            };
                            //println!("curve to");
                            //let x1 = chars.num().unwrap();
                            let y1 = chars.num().unwrap();
                            let x2 = chars.num().unwrap();
                            let y2 = chars.num().unwrap();
                            let x3 = chars.num().unwrap();
                            let y3 = chars.num().unwrap();
                            //TODO: set before
                            c.rel_curve_to(x1,y1,x2,y2,x3,y3);
                        }
                    },
                    'C' => {//relative curve
                        loop{//loop over the numbers
                            let x1 = match chars.num(){
                                Some(s) => s,
                                None => break
                            };
                            //println!("curve to");
                            let y1 = chars.num().unwrap();
                            let x2 = chars.num().unwrap();
                            let y2 = chars.num().unwrap();
                            let x3 = chars.num().unwrap();
                            let y3 = chars.num().unwrap();

                            //TODO: set before

                            c.curve_to(x1,y1,x2,y2,x3,y3);
                        }
                    },
                    's' => {
                        //TODO: make it work properly
                        loop{
                            let x2 = match chars.num(){
                                Some(s) => s,
                                None => break
                            };
                            let y2 = chars.num().unwrap();
                            let x  = chars.num().unwrap();
                            let y  = chars.num().unwrap();
                            let mut x1;
                            let mut y1;
                            match before{
                                None => {
                                    x1 = x2;
                                    y1 = y2;
                                },
                                Some((x,y)) => {
                                    x1 = x;
                                    y1 = y;
                                }
                            }
                            c.rel_curve_to(x2,y2,x1,y1,x,y);
                            //println!("s");
                        }
                    },
                    'S' => {
                        loop{
                            let x2 = match chars.num(){
                                Some(s) => s,
                                None => break
                            };
                            let y2 = chars.num().unwrap();
                            let x  = chars.num().unwrap();
                            let y  = chars.num().unwrap();

                            let mut x1;
                            let mut y1;
                            match before{
                                None => {
                                    x1 = x2;
                                    y1 = y2;
                                },
                                Some((x,y)) => {
                                    x1 = x;
                                    y1 = y;
                                }
                            }

                            c.curve_to(x2,y2,x1,y1,x,y);
                            //println!("S");
                        }
                    },
                    //TODO: implement the following functions
                    'T' => {//quadratische bizar kurven
                        println!("T");
                    },
                    't' => {//quadratische bizar kurven
                        println!("t");
                    },
                    'A' => {//Bogenkurven
                        println!("A");
                    },
                    'a' => {//Bogenkurven
                        println!("a");
                    },
                    'q' => {//quadratic curve
                        println!("q");
                    },
                    'Q' => {
                        println!("Q");
                    },
                    ' ' => {},//ignore whitespaces
                    _ => {
                        println!("something else '{}'", cc);
                    }
                }
                //println!("ch: {}", cc);
            }
            c.stroke();
        });
        (0.0, 0.0)
    }
}
<commit_msg>add unimplemented macro for error output<commit_after>use Widget;
use CTX;
use std::str;
//use std::from_str::FromStr;

///a Widget used for monochrom vektor Icons.
pub struct Icon<'a>{
    path: &'a str,//a path like in svg
    pub fill: Option<(f64,f64,f64)>,
    color: (f64, f64, f64),
}

impl<'a> Icon<'a>{
    ///create a new icon form a given svg-path
    pub fn new(path: &'a str, color: (f64,f64,f64)) -> Icon<'a>{
        Icon{
            path: path,
            color: color,
            fill: None,
        }
    }
}

//internal struct to parse a svg-path
struct PathParser<'a>{
    chars: str::Chars<'a>,
    last: Option<char>,//last character to unread
    unread: bool,
}

impl<'a> PathParser<'a>{
    fn new(c: str::Chars<'a>) -> PathParser<'a>{
        PathParser{
            chars: c,
            last: None,
            unread: false,
        }
    }
    #[inline]
    fn next(&mut self) -> Option<char>{
        if self.unread{
            self.unread = false;
            self.last
        }else{
            self.last = self.chars.next();
            self.last
        }
    }
    #[inline]
    fn unread(&mut self){
        self.unread = true;
    }

    #[inline]
    fn skip_space(&mut self){
        loop{
            match self.next(){
                None => break,
                Some(c) => if !((c == ' ') | (c == ',')){
                    break;
                }
            }
        }
        self.unread();
    }

    #[inline]
    fn num(&mut self) -> Option<f64>{//closure to read from stream
        let mut b = String::new();
        self.skip_space();
        let mut cc = match self.next(){
            Some(e) => e,
            None => return None
        };
        if cc == '-'{//handle minus
            b.push(cc);
            cc = match self.next(){
                Some(e) => e,
                None => return None
            };
        }
        let mut nf = true;
        while cc.is_digit(10)|((cc == '.')&&nf){
            //println!("    {}", cc);
            if cc == '.'{
                nf = false;
            }
            b.push(cc);
            cc = match self.next(){
                Some(e) => e,
                None => return None
            };
        }
        self.unread();
        //println!("    {}", cc);
        //println!("num {}", b);
        from_str::<f64>(b.as_slice())
    }
}

impl<'a> Widget<()> for Icon<'a>{
    ///this function will render a svg path, if the path is not correct it will panic
    fn render(&mut self, ctx: &mut CTX<()>) -> (f64, f64) {
        ctx.draw(|c|{
            //Parsing and drawing logic
            //TODO: add this
            let (r,g,b) = self.color;
            let mut before: Option<(f64,f64)> = None;//for s path
            c.set_source_rgb(r, g, b);
            let mut chars = PathParser::new(self.path.chars());

            loop{
                //TODO: make multible comands work
                let cc = match chars.next(){
                    Some(e) => e,
                    None => break
                };
                match cc{
                    'M' => {//move to
                        let x = chars.num().unwrap();
                        let y = chars.num().unwrap();
                        c.move_to(x,y);
                        //println!("move to ({} {})", x, y);
                        before = None;
                    },
                    'm' => {//move to
                        let x = chars.num().unwrap();
                        let y = chars.num().unwrap();
                        c.rel_move_to(x,y);
                        before = None;
                    },
                    'L' => {//line to
                        loop{//loop over the numbers
                            let x = match chars.num(){
                                Some(s) => s,
                                None => break
                            };
                            let y = chars.num().unwrap();
                            c.line_to(x,y);
                            //println!("line to ({} {})",x,y);
                        }
                        before = None;
                    },
                    'l' => {//line to
                        //println!("line to relative");
                        loop{//loop over the numbers
                            let x = match chars.num(){
                                Some(s) => s,
                                None => break
                            };
                            let y = chars.num().unwrap();
                            c.rel_line_to(x,y);
                            //println!("line to ({} {})",x,y);
                        }
                        before = None;
                    },
                    'V' => {//vertical line
                        //println!("vertival line");
                        c.line_to(0.0,chars.num().unwrap());
                        before = None;
                    },
                    'v' => {//vertical line
                        //println!("vertival line relative");
                        c.rel_line_to(0.0,chars.num().unwrap());
                        before = None;
                    },
                    'H' => {//horizontal line
                        c.line_to(chars.num().unwrap(),0.0);
                        before = None;
                        //println!("horizontal line");
                    },
                    'h' => {//horizontal line
                        before = None;
                        c.rel_line_to(chars.num().unwrap(),0.0);
                        //println!("horizontal line relative");
                    },
                    'Z' | 'z' => {//close path
                        //println!("close path");
                        before = None;
                        c.close_path();
                    },
                    'c' => {//relative curve
                        loop{//loop over the numbers
                            let x1 = match chars.num(){
                                Some(s) => s,
                                None => break
                            };
                            //println!("curve to");
                            //let x1 = chars.num().unwrap();
                            let y1 = chars.num().unwrap();
                            let x2 = chars.num().unwrap();
                            let y2 = chars.num().unwrap();
                            let x3 = chars.num().unwrap();
                            let y3 = chars.num().unwrap();
                            //TODO: set before
                            c.rel_curve_to(x1,y1,x2,y2,x3,y3);
                        }
                    },
                    'C' => {//relative curve
                        loop{//loop over the numbers
                            let x1 = match chars.num(){
                                Some(s) => s,
                                None => break
                            };
                            //println!("curve to");
                            let y1 = chars.num().unwrap();
                            let x2 = chars.num().unwrap();
                            let y2 = chars.num().unwrap();
                            let x3 = chars.num().unwrap();
                            let y3 = chars.num().unwrap();

                            //TODO: set before

                            c.curve_to(x1,y1,x2,y2,x3,y3);
                        }
                    },
                    's' => {
                        //TODO: make it work properly
                        loop{
                            let x2 = match chars.num(){
                                Some(s) => s,
                                None => break
                            };
                            let y2 = chars.num().unwrap();
                            let x  = chars.num().unwrap();
                            let y  = chars.num().unwrap();
                            let mut x1;
                            let mut y1;
                            match before{
                                None => {
                                    x1 = x2;
                                    y1 = y2;
                                },
                                Some((x,y)) => {
                                    x1 = x;
                                    y1 = y;
                                }
                            }
                            c.rel_curve_to(x2,y2,x1,y1,x,y);
                            //println!("s");
                        }
                    },
                    'S' => {
                        loop{
                            let x2 = match chars.num(){
                                Some(s) => s,
                                None => break
                            };
                            let y2 = chars.num().unwrap();
                            let x  = chars.num().unwrap();
                            let y  = chars.num().unwrap();

                            let mut x1;
                            let mut y1;
                            match before{
                                None => {
                                    x1 = x2;
                                    y1 = y2;
                                },
                                Some((x,y)) => {
                                    x1 = x;
                                    y1 = y;
                                }
                            }

                            c.curve_to(x2,y2,x1,y1,x,y);
                            //println!("S");
                        }
                    },
                    //TODO: implement the following functions
                    'T' => {//quadratische bizar kurven
                        println!("T");
                        unimplemented!();
                    },
                    't' => {//quadratische bizar kurven
                        println!("t");
                        unimplemented!();
                    },
                    'A' => {//Bogenkurven
                        println!("A");
                        unimplemented!();
                    },
                    'a' => {//Bogenkurven
                        println!("a");
                        unimplemented!();
                    },
                    'q' => {//quadratic curve
                        println!("q");
                        unimplemented!();
                    },
                    'Q' => {
                        println!("Q");
                        unimplemented!();
                    },
                    ' ' => {},//ignore whitespaces
                    _ => {
                        println!("something else '{}'", cc);
                    }
                }
                //println!("ch: {}", cc);
            }
            c.stroke();
        });
        (0.0, 0.0)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2021 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use core::convert::Infallible;
use std::time::Duration;

use embedded_hal::digital::blocking::{
    InputPin as InputPinHal, StatefulOutputPin as StatefulOutputPinHal,
    ToggleableOutputPin as ToggleableOutputPinHal,
};
use embedded_hal::pwm::blocking::Pwm as PwmHal;

use super::{InputPin, IoPin, OutputPin, Pin};
use crate::gpio::Mode;

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for Pin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for InputPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for IoPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for OutputPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `StatefulOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::StatefulOutputPin for IoPin {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_high(self)
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_low(self)
    }
}

/// Unproven `StatefulOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::StatefulOutputPin for OutputPin {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_high(self)
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_low(self)
    }
}

/// Unproven `ToggleableOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::ToggleableOutputPin for IoPin {
    type Error = Infallible;

    fn toggle(&mut self) -> Result<(), Self::Error> {
        ToggleableOutputPinHal::toggle(self)
    }
}

/// Unproven `ToggleableOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::ToggleableOutputPin for OutputPin {
    type Error = Infallible;

    fn toggle(&mut self) -> Result<(), Self::Error> {
        ToggleableOutputPinHal::toggle(self)
    }
}

/// Unproven `Pwm` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::Pwm for OutputPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`.
    fn disable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::disable(self, &channel);
    }

    /// Enables a PWM `channel`.
    fn enable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::enable(self, &channel);
    }

    /// Returns the current PWM period.
    fn get_period(&self) -> Self::Time {
        PwmHal::get_period(self).unwrap_or_default()
    }

    /// Returns the current duty cycle.
    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
        PwmHal::get_duty(self, &channel).unwrap_or_default()
    }

    /// Returns the maximum duty cycle value.
    fn get_max_duty(&self) -> Self::Duty {
        PwmHal::get_max_duty(self).unwrap_or(1.0)
    }

    /// Sets a new duty cycle.
    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
        let _ = PwmHal::set_duty(self, &channel, duty);
    }

    /// Sets a new PWM period.
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let _ = PwmHal::set_period(self, period);
    }
}

/// Unproven `Pwm` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::Pwm for IoPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`.
    fn disable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::disable(self, &channel);
    }

    /// Enables a PWM `channel`.
    fn enable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::enable(self, &channel);
    }

    /// Returns the current PWM period.
    fn get_period(&self) -> Self::Time {
        PwmHal::get_period(self).unwrap_or_default()
    }

    /// Returns the current duty cycle.
    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
        PwmHal::get_duty(self, &channel).unwrap_or_default()
    }

    /// Returns the maximum duty cycle value.
    fn get_max_duty(&self) -> Self::Duty {
        PwmHal::get_max_duty(self).unwrap_or(1.0)
    }

    /// Sets a new duty cycle.
    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
        let _ = PwmHal::set_duty(self, &channel, duty);
    }

    /// Sets a new PWM period.
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let _ = PwmHal::set_period(self, period);
    }
}

/// Unproven `IoPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::IoPin<IoPin, IoPin> for IoPin {

    type Error = Infallible;

    /// Tries to convert this pin to input mode.
    ///
    /// If the pin is already in input mode, this method should succeed.
    fn into_input_pin(mut self) -> Result<IoPin, Self::Error> {
        let now_mode = self.mode();
        return if now_mode == Mode::Input {
            Ok(self)
        } else {
            self.set_mode(Mode::Input);
            Ok(self)
        };
    }

    /// Tries to convert this pin to output mode with the given initial state.
    ///
    /// If the pin is already in the requested state, this method should
    /// succeed.
    fn into_output_pin(mut self, state: embedded_hal_0::digital::v2::PinState) -> Result<IoPin, Self::Error> {
        let now_mode = self.mode();

        return if now_mode == Mode::Output {
            Ok(self)
        } else {
            self.set_mode(Mode::Output);
            match state {
                embedded_hal_0::digital::v2::PinState::Low => self.set_low() ,
                embedded_hal_0::digital::v2::PinState::High => self.set_high()
            }
            Ok(self)
        };
    }
}
<commit_msg>Should always change state while switching to output pin<commit_after>// Copyright (c) 2017-2021 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use core::convert::Infallible;
use std::time::Duration;

use embedded_hal::digital::blocking::{
    InputPin as InputPinHal, StatefulOutputPin as StatefulOutputPinHal,
    ToggleableOutputPin as ToggleableOutputPinHal,
};
use embedded_hal::pwm::blocking::Pwm as PwmHal;

use super::{InputPin, IoPin, OutputPin, Pin};
use crate::gpio::Mode;

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for Pin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for InputPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for IoPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `InputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::InputPin for OutputPin {
    type Error = Infallible;

    fn is_high(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_high(self)
    }

    fn is_low(&self) -> Result<bool, Self::Error> {
        InputPinHal::is_low(self)
    }
}

/// Unproven `StatefulOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::StatefulOutputPin for IoPin {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_high(self)
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_low(self)
    }
}

/// Unproven `StatefulOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::StatefulOutputPin for OutputPin {
    fn is_set_high(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_high(self)
    }

    fn is_set_low(&self) -> Result<bool, Self::Error> {
        StatefulOutputPinHal::is_set_low(self)
    }
}

/// Unproven `ToggleableOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::ToggleableOutputPin for IoPin {
    type Error = Infallible;

    fn toggle(&mut self) -> Result<(), Self::Error> {
        ToggleableOutputPinHal::toggle(self)
    }
}

/// Unproven `ToggleableOutputPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::ToggleableOutputPin for OutputPin {
    type Error = Infallible;

    fn toggle(&mut self) -> Result<(), Self::Error> {
        ToggleableOutputPinHal::toggle(self)
    }
}

/// Unproven `Pwm` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::Pwm for OutputPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`.
    fn disable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::disable(self, &channel);
    }

    /// Enables a PWM `channel`.
    fn enable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::enable(self, &channel);
    }

    /// Returns the current PWM period.
    fn get_period(&self) -> Self::Time {
        PwmHal::get_period(self).unwrap_or_default()
    }

    /// Returns the current duty cycle.
    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
        PwmHal::get_duty(self, &channel).unwrap_or_default()
    }

    /// Returns the maximum duty cycle value.
    fn get_max_duty(&self) -> Self::Duty {
        PwmHal::get_max_duty(self).unwrap_or(1.0)
    }

    /// Sets a new duty cycle.
    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
        let _ = PwmHal::set_duty(self, &channel, duty);
    }

    /// Sets a new PWM period.
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let _ = PwmHal::set_period(self, period);
    }
}

/// Unproven `Pwm` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::Pwm for IoPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`.
    fn disable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::disable(self, &channel);
    }

    /// Enables a PWM `channel`.
    fn enable(&mut self, channel: Self::Channel) {
        let _ = PwmHal::enable(self, &channel);
    }

    /// Returns the current PWM period.
    fn get_period(&self) -> Self::Time {
        PwmHal::get_period(self).unwrap_or_default()
    }

    /// Returns the current duty cycle.
    fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
        PwmHal::get_duty(self, &channel).unwrap_or_default()
    }

    /// Returns the maximum duty cycle value.
    fn get_max_duty(&self) -> Self::Duty {
        PwmHal::get_max_duty(self).unwrap_or(1.0)
    }

    /// Sets a new duty cycle.
    fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
        let _ = PwmHal::set_duty(self, &channel, duty);
    }

    /// Sets a new PWM period.
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let _ = PwmHal::set_period(self, period);
    }
}

/// Unproven `IoPin` trait implementation for `embedded-hal` v0.2.6.
impl embedded_hal_0::digital::v2::IoPin<IoPin, IoPin> for IoPin {

    type Error = Infallible;

    /// Tries to convert this pin to input mode.
    ///
    /// If the pin is already in input mode, this method should succeed.
    fn into_input_pin(mut self) -> Result<IoPin, Self::Error> {
        let now_mode = self.mode();
        return if now_mode == Mode::Input {
            Ok(self)
        } else {
            self.set_mode(Mode::Input);
            Ok(self)
        };
    }

    /// Tries to convert this pin to output mode with the given initial state.
    ///
    /// If the pin is already in the requested state, this method should
    /// succeed.
    fn into_output_pin(mut self, state: embedded_hal_0::digital::v2::PinState) -> Result<IoPin, Self::Error> {
        let now_mode = self.mode();

        return if now_mode == Mode::Output {
            match state {
                embedded_hal_0::digital::v2::PinState::Low => self.set_low() ,
                embedded_hal_0::digital::v2::PinState::High => self.set_high()
            }
            Ok(self)
        } else {
            self.set_mode(Mode::Output);
            match state {
                embedded_hal_0::digital::v2::PinState::Low => self.set_low() ,
                embedded_hal_0::digital::v2::PinState::High => self.set_high()
            }
            Ok(self)
        };
    }
}
<|endoftext|>