<commit_before>// Copyright 2016 oauth-client-rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! OAuth 1.0 client library for Rust.
//!
//! Dependent on libcurl.
//!
//! [Repository](https://github.com/charlag/oauth-client-rs)
//!
//! # Examples
//!
//! Send request for request token.
//!
//! ```
//! const REQUEST_TOKEN: &'static str = "http://oauthbin.com/v1/request-token";
//! let consumer = oauth_client::Token::new("key", "secret");
//! let bytes = oauth_client::get(REQUEST_TOKEN, &consumer, None, None).unwrap();
//! ```

#![warn(bad_style)]
#![warn(missing_docs)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate crypto;
extern crate curl;
#[macro_use]
extern crate log;
extern crate rand;
extern crate rustc_serialize;
extern crate time;
extern crate url;

use std::borrow::Cow;
use std::collections::HashMap;
use std::io::Read;
use std::{error, fmt};
use rand::Rng;
use rustc_serialize::base64::{self, ToBase64};
use crypto::hmac::Hmac;
use crypto::mac::{Mac, MacResult};
use crypto::sha1::Sha1;
use curl::easy::{Easy, List};
use url::percent_encoding;

/// The `Error` type
#[derive(Debug)]
pub enum Error {
    /// Curl error
    Curl(curl::Error),
    /// Http status
    HttpStatus(u32),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Curl(ref err) => write!(f, "Curl error: {}", err),
            Error::HttpStatus(ref resp) => write!(f, "HTTP status error: {}", resp),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Curl(ref err) => err.description(),
            Error::HttpStatus(_) => "HTTP status error",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Curl(ref err) => Some(err),
            Error::HttpStatus(_) => None,
        }
    }
}

impl From<curl::Error> for Error {
    fn from(err: curl::Error) -> Error {
        Error::Curl(err)
    }
}

/// Token structure for the OAuth
#[derive(Clone, Debug)]
pub struct Token<'a> {
    /// 'key' field of the token
    pub key: Cow<'a, str>,
    /// 'secret' part of the token
    pub secret: Cow<'a, str>,
}

impl<'a> Token<'a> {
    /// Create new token from `key` and `secret`
    ///
    /// # Examples
    ///
    /// ```
    /// let consumer = oauth_client::Token::new("key", "secret");
    /// ```
    pub fn new<K, S>(key: K, secret: S) -> Token<'a>
        where K: Into<Cow<'a, str>>,
              S: Into<Cow<'a, str>>
    {
        Token {
            key: key.into(),
            secret: secret.into(),
        }
    }
}

/// Alias for `HashMap<Cow<'a, str>, Cow<'a, str>>`
pub type ParamList<'a> = HashMap<Cow<'a, str>, Cow<'a, str>>;

fn insert_param<'a, K, V>(param: &mut ParamList<'a>, key: K, value: V) -> Option<Cow<'a, str>>
    where K: Into<Cow<'a, str>>,
          V: Into<Cow<'a, str>>
{
    param.insert(key.into(), value.into())
}

fn join_query<'a>(param: &ParamList<'a>) -> String {
    let mut pairs = param.iter()
                         .map(|(k, v)| format!("{}={}", encode(&k), encode(&v)))
                         .collect::<Vec<_>>();
    pairs.sort();
    pairs.join("&")
}

/// Percent encode string
fn encode(s: &str) -> String {
    percent_encoding::utf8_percent_encode(s, percent_encoding::FORM_URLENCODED_ENCODE_SET)
}

/// Wrapper function around 'crypto::Hmac'
fn hmac_sha1(key: &[u8], data: &[u8]) -> MacResult {
    let mut hmac = Hmac::new(Sha1::new(), key);
    hmac.input(data);
    hmac.result()
}

/// Create signature. See https://dev.twitter.com/oauth/overview/creating-signatures
fn signature(method: &str,
             uri: &str,
             query: &str,
             consumer_secret: &str,
             token_secret: Option<&str>)
             -> String {
    let base = format!("{}&{}&{}", encode(method), encode(uri), encode(query));
    let key = format!("{}&{}",
                      encode(consumer_secret),
                      encode(token_secret.unwrap_or("")));
    let conf = base64::Config {
        char_set: base64::CharacterSet::Standard,
        newline: base64::Newline::LF,
        pad: true,
        line_length: None,
    };
    debug!("Signature base string: {}", base);
    debug!("Authorization header: Authorization: {}", base);
    hmac_sha1(key.as_bytes(), base.as_bytes()).code().to_base64(conf)
}

/// Constuct plain-text header
fn header(param: &ParamList) -> String {
    let mut pairs = param.iter()
                         .filter(|&(k, _)| k.starts_with("oauth_"))
                         .map(|(k, v)| format!("{}=\"{}\"", k, encode(&v)))
                         .collect::<Vec<_>>();
    pairs.sort();
    format!("OAuth {}", pairs.join(", "))
}

/// Construct plain-text body from 'PaaramList'
fn body(param: &ParamList) -> String {
    let mut pairs = param.iter()
                         .filter(|&(k, _)| !k.starts_with("oauth_"))
                         .map(|(k, v)| format!("{}={}", k, encode(&v)))
                         .collect::<Vec<_>>();
    pairs.sort();
    format!("{}", pairs.join("&"))
}

/// Create header and body
fn get_header(method: &str,
              uri: &str,
              consumer: &Token,
              token: Option<&Token>,
              other_param: Option<&ParamList>)
              -> (String, String) {
    let mut param = HashMap::new();
    let timestamp = format!("{}", time::now_utc().to_timespec().sec);
    let nonce = rand::thread_rng().gen_ascii_chars().take(32).collect::<String>();

    let _ = insert_param(&mut param, "oauth_consumer_key", consumer.key.to_string());
    let _ = insert_param(&mut param, "oauth_nonce", nonce);
    let _ = insert_param(&mut param, "oauth_signature_method", "HMAC-SHA1");
    let _ = insert_param(&mut param, "oauth_timestamp", timestamp);
    let _ = insert_param(&mut param, "oauth_version", "1.0");
    if let Some(tk) = token {
        let _ = insert_param(&mut param, "oauth_token", tk.key.as_ref());
    }

    if let Some(ps) = other_param {
        for (k, v) in ps.iter() {
            let _ = insert_param(&mut param, k.as_ref(), v.as_ref());
        }
    }

    let sign = signature(method,
                         uri,
                         join_query(&param).as_ref(),
                         consumer.secret.as_ref(),
                         token.map(|t| t.secret.as_ref()));
    let _ = insert_param(&mut param, "oauth_signature", sign);

    (header(&param), body(&param))
}

/// Create an authorization header.
/// See https://dev.twitter.com/oauth/overview/authorizing-requests
///
/// # Examples
///
/// ```
/// # extern crate curl;
/// # extern crate oauth_client;
/// # fn main() {
/// const REQUEST_TOKEN: &'static str = "http://oauthbin.com/v1/request-token";
/// let consumer = oauth_client::Token::new("key", "secret");
/// let header = oauth_client::authorization_header("GET", REQUEST_TOKEN, &consumer, None, None);
/// # }
/// ```
pub fn authorization_header(method: &str,
                            uri: &str,
                            consumer: &Token,
                            token: Option<&Token>,
                            other_param: Option<&ParamList>)
                            -> String {
    get_header(method, uri, consumer, token, other_param).0
}

/// Send authorized GET request to the specified URL.
/// `consumer` is a consumer token.
///
/// # Examples
///
/// ```
/// let REQUEST_TOKEN: &'static str = "http://oauthbin.com/v1/request-token";
/// let consumer = oauth_client::Token::new("key", "secret");
/// let bytes = oauth_client::get(REQUEST_TOKEN, &consumer, None, None).unwrap();
/// let resp = String::from_utf8(bytes).unwrap();
/// ```
pub fn get(uri: &str,
           consumer: &Token,
           token: Option<&Token>,
           other_param: Option<&ParamList>)
           -> Result<Vec<u8>, Error> {
    let (header, body) = get_header("GET", uri, consumer, token, other_param);
    let req_uri = if body.len() > 0 {
        format!("{}?{}", uri, body)
    } else {
        format!("{}", uri)
    };
    let mut handle = Easy::new();
    let mut list = List::new();
    list.append(format!("Authorization: {}", header).as_ref()).unwrap();
    let mut resp = Vec::new();
    try!(handle.url(req_uri.as_ref()));
    try!(handle.http_headers(list));
    try!(handle.get(true));
    {
        let mut transfer = handle.transfer();
        try!(transfer.write_function(|data| {
            resp.extend_from_slice(data);
            Ok(data.len())
        }));
        try!(transfer.perform());
    }
    let code = try!(handle.response_code());
    if code != 200 {
        return Err(Error::HttpStatus(code))
    }
    Ok(resp)
}

/// Send authorized POST request to the specified URL.
/// `consumer` is a consumer token.
///
/// # Examples
///
/// ```
/// # let request = oauth_client::Token::new("key", "secret");
/// let ACCESS_TOKEN: &'static str = "http://oauthbin.com/v1/access-token";
/// let consumer = oauth_client::Token::new("key", "secret");
/// let bytes = oauth_client::post(ACCESS_TOKEN, &consumer, Some(&request), None).unwrap();
/// let resp = String::from_utf8(bytes).unwrap();
/// ```
pub fn post(uri: &str,
            consumer: &Token,
            token: Option<&Token>,
            other_param: Option<&ParamList>)
            -> Result<Vec<u8>, Error> {
    let (header, body) = get_header("POST", uri, consumer, token, other_param);
    let mut handle = Easy::new();
    let mut list = List::new();
    list.append(format!("Authorization: {}", header).as_ref()).unwrap();
    let mut resp = Vec::new();
    try!(handle.url(uri.as_ref()));
    try!(handle.http_headers(list));
    try!(handle.post(true));
    try!(handle.post_field_size(body.len() as u64));
    {
        let mut transfer = handle.transfer();
        try!(transfer.read_function(|into| {
            let mut body = body.as_bytes();
            Ok(body.read(into).unwrap())
        }));
        try!(transfer.write_function(|data| {
            resp.extend_from_slice(data);
            Ok(data.len())
        }));
        try!(transfer.perform());
    }
    let code = try!(handle.response_code());
    if code != 200 {
        return Err(Error::HttpStatus(code))
    }
    Ok(resp)
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;

    #[test]
    fn query() {
        let mut map = HashMap::new();
        let _ = map.insert("aaa".into(), "AAA".into());
        let _ = map.insert("bbbb".into(), "BBBB".into());
        let query = super::join_query(&map);
        assert_eq!("aaa=AAA&bbbb=BBBB", query);
    }
}
<commit_msg>add some tests for the percent encoding<commit_after>// Copyright 2016 oauth-client-rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! OAuth 1.0 client library for Rust.
//!
//! Dependent on libcurl.
//!
//! [Repository](https://github.com/charlag/oauth-client-rs)
//!
//! # Examples
//!
//! Send request for request token.
//!
//! ```
//! const REQUEST_TOKEN: &'static str = "http://oauthbin.com/v1/request-token";
//! let consumer = oauth_client::Token::new("key", "secret");
//! let bytes = oauth_client::get(REQUEST_TOKEN, &consumer, None, None).unwrap();
//! ```

#![warn(bad_style)]
#![warn(missing_docs)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate crypto;
extern crate curl;
#[macro_use]
extern crate log;
extern crate rand;
extern crate rustc_serialize;
extern crate time;
extern crate url;

use std::borrow::Cow;
use std::collections::HashMap;
use std::io::Read;
use std::{error, fmt};
use rand::Rng;
use rustc_serialize::base64::{self, ToBase64};
use crypto::hmac::Hmac;
use crypto::mac::{Mac, MacResult};
use crypto::sha1::Sha1;
use curl::easy::{Easy, List};
use url::percent_encoding;

/// The `Error` type
#[derive(Debug)]
pub enum Error {
    /// Curl error
    Curl(curl::Error),
    /// Http status
    HttpStatus(u32),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Curl(ref err) => write!(f, "Curl error: {}", err),
            Error::HttpStatus(ref resp) => write!(f, "HTTP status error: {}", resp),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Curl(ref err) => err.description(),
            Error::HttpStatus(_) => "HTTP status error",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Curl(ref err) => Some(err),
            Error::HttpStatus(_) => None,
        }
    }
}

impl From<curl::Error> for Error {
    fn from(err: curl::Error) -> Error {
        Error::Curl(err)
    }
}

/// Token structure for the OAuth
#[derive(Clone, Debug)]
pub struct Token<'a> {
    /// 'key' field of the token
    pub key: Cow<'a, str>,
    /// 'secret' part of the token
    pub secret: Cow<'a, str>,
}

impl<'a> Token<'a> {
    /// Create new token from `key` and `secret`
    ///
    /// # Examples
    ///
    /// ```
    /// let consumer = oauth_client::Token::new("key", "secret");
    /// ```
    pub fn new<K, S>(key: K, secret: S) -> Token<'a>
        where K: Into<Cow<'a, str>>,
              S: Into<Cow<'a, str>>
    {
        Token {
            key: key.into(),
            secret: secret.into(),
        }
    }
}

/// Alias for `HashMap<Cow<'a, str>, Cow<'a, str>>`
pub type ParamList<'a> = HashMap<Cow<'a, str>, Cow<'a, str>>;

fn insert_param<'a, K, V>(param: &mut ParamList<'a>, key: K, value: V) -> Option<Cow<'a, str>>
    where K: Into<Cow<'a, str>>,
          V: Into<Cow<'a, str>>
{
    param.insert(key.into(), value.into())
}

fn join_query<'a>(param: &ParamList<'a>) -> String {
    let mut pairs = param.iter()
                         .map(|(k, v)| format!("{}={}", encode(&k), encode(&v)))
                         .collect::<Vec<_>>();
    pairs.sort();
    pairs.join("&")
}

/// Percent encode string
fn encode(s: &str) -> String {
    percent_encoding::utf8_percent_encode(s, percent_encoding::FORM_URLENCODED_ENCODE_SET)
}

/// Wrapper function around 'crypto::Hmac'
fn hmac_sha1(key: &[u8], data: &[u8]) -> MacResult {
    let mut hmac = Hmac::new(Sha1::new(), key);
    hmac.input(data);
    hmac.result()
}

/// Create signature. See https://dev.twitter.com/oauth/overview/creating-signatures
fn signature(method: &str,
             uri: &str,
             query: &str,
             consumer_secret: &str,
             token_secret: Option<&str>)
             -> String {
    let base = format!("{}&{}&{}", encode(method), encode(uri), encode(query));
    let key = format!("{}&{}",
                      encode(consumer_secret),
                      encode(token_secret.unwrap_or("")));
    let conf = base64::Config {
        char_set: base64::CharacterSet::Standard,
        newline: base64::Newline::LF,
        pad: true,
        line_length: None,
    };
    debug!("Signature base string: {}", base);
    debug!("Authorization header: Authorization: {}", base);
    hmac_sha1(key.as_bytes(), base.as_bytes()).code().to_base64(conf)
}

/// Constuct plain-text header
fn header(param: &ParamList) -> String {
    let mut pairs = param.iter()
                         .filter(|&(k, _)| k.starts_with("oauth_"))
                         .map(|(k, v)| format!("{}=\"{}\"", k, encode(&v)))
                         .collect::<Vec<_>>();
    pairs.sort();
    format!("OAuth {}", pairs.join(", "))
}

/// Construct plain-text body from 'PaaramList'
fn body(param: &ParamList) -> String {
    let mut pairs = param.iter()
                         .filter(|&(k, _)| !k.starts_with("oauth_"))
                         .map(|(k, v)| format!("{}={}", k, encode(&v)))
                         .collect::<Vec<_>>();
    pairs.sort();
    format!("{}", pairs.join("&"))
}

/// Create header and body
fn get_header(method: &str,
              uri: &str,
              consumer: &Token,
              token: Option<&Token>,
              other_param: Option<&ParamList>)
              -> (String, String) {
    let mut param = HashMap::new();
    let timestamp = format!("{}", time::now_utc().to_timespec().sec);
    let nonce = rand::thread_rng().gen_ascii_chars().take(32).collect::<String>();

    let _ = insert_param(&mut param, "oauth_consumer_key", consumer.key.to_string());
    let _ = insert_param(&mut param, "oauth_nonce", nonce);
    let _ = insert_param(&mut param, "oauth_signature_method", "HMAC-SHA1");
    let _ = insert_param(&mut param, "oauth_timestamp", timestamp);
    let _ = insert_param(&mut param, "oauth_version", "1.0");
    if let Some(tk) = token {
        let _ = insert_param(&mut param, "oauth_token", tk.key.as_ref());
    }

    if let Some(ps) = other_param {
        for (k, v) in ps.iter() {
            let _ = insert_param(&mut param, k.as_ref(), v.as_ref());
        }
    }

    let sign = signature(method,
                         uri,
                         join_query(&param).as_ref(),
                         consumer.secret.as_ref(),
                         token.map(|t| t.secret.as_ref()));
    let _ = insert_param(&mut param, "oauth_signature", sign);

    (header(&param), body(&param))
}

/// Create an authorization header.
/// See https://dev.twitter.com/oauth/overview/authorizing-requests
///
/// # Examples
///
/// ```
/// # extern crate curl;
/// # extern crate oauth_client;
/// # fn main() {
/// const REQUEST_TOKEN: &'static str = "http://oauthbin.com/v1/request-token";
/// let consumer = oauth_client::Token::new("key", "secret");
/// let header = oauth_client::authorization_header("GET", REQUEST_TOKEN, &consumer, None, None);
/// # }
/// ```
pub fn authorization_header(method: &str,
                            uri: &str,
                            consumer: &Token,
                            token: Option<&Token>,
                            other_param: Option<&ParamList>)
                            -> String {
    get_header(method, uri, consumer, token, other_param).0
}

/// Send authorized GET request to the specified URL.
/// `consumer` is a consumer token.
///
/// # Examples
///
/// ```
/// let REQUEST_TOKEN: &'static str = "http://oauthbin.com/v1/request-token";
/// let consumer = oauth_client::Token::new("key", "secret");
/// let bytes = oauth_client::get(REQUEST_TOKEN, &consumer, None, None).unwrap();
/// let resp = String::from_utf8(bytes).unwrap();
/// ```
pub fn get(uri: &str,
           consumer: &Token,
           token: Option<&Token>,
           other_param: Option<&ParamList>)
           -> Result<Vec<u8>, Error> {
    let (header, body) = get_header("GET", uri, consumer, token, other_param);
    let req_uri = if body.len() > 0 {
        format!("{}?{}", uri, body)
    } else {
        format!("{}", uri)
    };
    let mut handle = Easy::new();
    let mut list = List::new();
    list.append(format!("Authorization: {}", header).as_ref()).unwrap();
    let mut resp = Vec::new();
    try!(handle.url(req_uri.as_ref()));
    try!(handle.http_headers(list));
    try!(handle.get(true));
    {
        let mut transfer = handle.transfer();
        try!(transfer.write_function(|data| {
            resp.extend_from_slice(data);
            Ok(data.len())
        }));
        try!(transfer.perform());
    }
    let code = try!(handle.response_code());
    if code != 200 {
        return Err(Error::HttpStatus(code))
    }
    Ok(resp)
}

/// Send authorized POST request to the specified URL.
/// `consumer` is a consumer token.
///
/// # Examples
///
/// ```
/// # let request = oauth_client::Token::new("key", "secret");
/// let ACCESS_TOKEN: &'static str = "http://oauthbin.com/v1/access-token";
/// let consumer = oauth_client::Token::new("key", "secret");
/// let bytes = oauth_client::post(ACCESS_TOKEN, &consumer, Some(&request), None).unwrap();
/// let resp = String::from_utf8(bytes).unwrap();
/// ```
pub fn post(uri: &str,
            consumer: &Token,
            token: Option<&Token>,
            other_param: Option<&ParamList>)
            -> Result<Vec<u8>, Error> {
    let (header, body) = get_header("POST", uri, consumer, token, other_param);
    let mut handle = Easy::new();
    let mut list = List::new();
    list.append(format!("Authorization: {}", header).as_ref()).unwrap();
    let mut resp = Vec::new();
    try!(handle.url(uri.as_ref()));
    try!(handle.http_headers(list));
    try!(handle.post(true));
    try!(handle.post_field_size(body.len() as u64));
    {
        let mut transfer = handle.transfer();
        try!(transfer.read_function(|into| {
            let mut body = body.as_bytes();
            Ok(body.read(into).unwrap())
        }));
        try!(transfer.write_function(|data| {
            resp.extend_from_slice(data);
            Ok(data.len())
        }));
        try!(transfer.perform());
    }
    let code = try!(handle.response_code());
    if code != 200 {
        return Err(Error::HttpStatus(code))
    }
    Ok(resp)
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use super::encode;

    #[test]
    fn query() {
        let mut map = HashMap::new();
        let _ = map.insert("aaa".into(), "AAA".into());
        let _ = map.insert("bbbb".into(), "BBBB".into());
        let query = super::join_query(&map);
        assert_eq!("aaa=AAA&bbbb=BBBB", query);
    }

    #[test]
    fn test_encode() {
        let method = "GET";
        let uri = "http://oauthbin.com/v1/request-token";
        let encoded_uri = "http%3A%2F%2Foauthbin.com%2Fv1%2Frequest-token";
        let query = "oauth_consumer_key=key&oauth_nonce=s6HGl3GhmsDsmpgeLo6lGtKs7rQEzzsA&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1471445561&oauth_version=1.\
                     0";
        let encoded_query = "oauth_consumer_key%3Dkey%26oauth_nonce%3Ds6HGl3GhmsDsmpgeLo6lGtKs7rQEzzsA%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1471445561%26oauth_version%3D1.\
                             0";

        assert_eq!(encode(method), "GET");
        assert_eq!(encode(uri), encoded_uri);
        assert_eq!(encode(query), encoded_query);
    }
}
<|endoftext|>


<commit_before>extern crate nalgebra as na;
extern crate num;

use na::{Norm, FloatPnt, FloatVec};
use num::Zero;
use std::cmp;

/// Wraps a square distance.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct SqDist(pub f32);

impl SqDist {
    pub fn from_dist(d: f32) -> SqDist {
        SqDist(d.powi(2))
    }
}

/// What to do when a node `connects` with an attrator.
#[derive(Debug, Copy, Clone)]
pub enum ConnectAction {
    KillAttractor,
    DisableFor {
        iterations: u32,
    },
}

#[derive(Debug, Copy, Clone)]
pub struct Attractor<P, I> {
    /// The radius^2 within which it can influence a Node.
    attract_radius_sq: SqDist,

    /// If there is a node closer than the square root of
    /// this radius, the information is exchanged with the
    /// node and the ```connect_action``` is performed.
    /// This can be for example: kill the attractor,
    /// or disable it for a while.
    connect_radius_sq: SqDist,

    /// The strenght with which it influences a Node.
    strength: f32,

    /// The position of the attractor.
    pub position: P,

    /// The attractor carries a bit of information.
    /// When a node comes closer than ```connect_radius```
    /// this bit of information is exchanged.
    information: I,

    /// Action performed when a node comes closer
    /// than ```connect_radius```.
    connect_action: ConnectAction,
}

struct Node<P, F> {
    /// Index of the direct parent.
    parent: usize,

    /// Number of nodes between this node and the root node.
    length: usize,

    /// Index of the root node this node is associated with.
    root: usize,

    /// The node's coordinate position.
    position: P,

    // The active_lifetime of a node is reduced every
    // time it is found being the closest node to some
    // attraction point. If it hits 0, the node
    // is no longer used.
    active_lifetime: i32,
    // The inactive_lifetime is reduce whenever a node
    // is not being found as the closest towards an
    // attraction point.
    inactive_lifetime: i32,

    growth: F,
    growth_count: u32,
}
impl<P, F> Node<P, F> {
    fn send_information(&mut self, _information: ()) {}
}

pub struct SpaceColonization<P, F>
    where P: FloatPnt<f32, F>,
          F: FloatVec<f32> + Zero + Copy
{
    nodes: Vec<Node<P, F>>,
    attractors: Vec<Attractor<P, ()>>,
    default_active_lifetime: i32,
    default_inactive_lifetime: i32,
    default_attract_radius_sq: SqDist,
    default_connect_radius_sq: SqDist,
}

impl<P, F> SpaceColonization<P, F>
    where P: FloatPnt<f32, F>,
          F: FloatVec<f32> + Zero + Copy
{
    pub fn new(default_active_lifetime: i32,
               default_inactive_lifetime: i32,
               default_attract_radius_sq: SqDist,
               default_connect_radius_sq: SqDist)
               -> SpaceColonization<P, F> {
        SpaceColonization {
            nodes: Vec::new(),
            attractors: Vec::new(),
            default_active_lifetime: default_active_lifetime,
            default_inactive_lifetime: default_inactive_lifetime,
            default_attract_radius_sq: default_attract_radius_sq,
            default_connect_radius_sq: default_connect_radius_sq,
        }
    }

    pub fn attractors(&self) -> &[Attractor<P, ()>] {
        &self.attractors
    }

    pub fn add_attractor(&mut self, position: P) {
        self.attractors.push(Attractor {
            attract_radius_sq: self.default_attract_radius_sq,
            connect_radius_sq: self.default_connect_radius_sq,
            strength: 1.0,
            position: position,
            information: (),
            connect_action: ConnectAction::KillAttractor,
        });
    }

    pub fn add_root_node(&mut self, position: P) {
        self.add_node(position, None);
    }

    fn add_node(&mut self, position: P, parent: Option<usize>) {
        // NOTE: a root node has it's own index as parent and root.
        let len = self.nodes.len();
        let (parent, root, length) = match parent {
            Some(p) => {
                assert!(p < len);
                (p, self.nodes[p].root, self.nodes[p].length + 1)
            }
            None => (len, len, 0),
        };

        self.nodes.push(Node {
            parent: parent,
            root: root,
            length: length,
            position: position,
            active_lifetime: self.default_active_lifetime,
            inactive_lifetime: self.default_inactive_lifetime,
            growth: Zero::zero(),
            growth_count: 0,
        });
    }

    pub fn iter_segments<C>(&self, callback: &mut C)
        where C: FnMut(&P, &P)
    {
        for (i, node) in self.nodes.iter().enumerate() {
            if i != node.parent {
                callback(&node.position, &self.nodes[node.parent].position);
            }
        }
    }

    pub fn iterate(&mut self, move_distance: f32, use_last_n_nodes: Option<usize>) -> usize {
        let num_nodes = self.nodes.len();
        let use_last_nodes: usize = cmp::min(num_nodes, use_last_n_nodes.unwrap_or(num_nodes));
        let start_index = num_nodes - use_last_nodes;

        {
            let nodes = &mut self.nodes[start_index..];

            // for each attraction_point, find the nearest node that it influences
            let mut ap_idx = 0;
            'outer: while ap_idx < self.attractors.len() {
                let ap = self.attractors[ap_idx];

                // find the node nearest to the `ap` attraction point
                let mut nearest_node: Option<&mut Node<_, _>> = None;
                let mut nearest_distance_sq = ap.attract_radius_sq;
                let mut connect_node: Option<&mut Node<_, _>> = None;
                for node in nodes.iter_mut() {
                    if node.inactive_lifetime <= 0 || node.active_lifetime <= 0 {
                        // The node has become inactive
                        continue;
                    }

                    let dist_sq = SqDist(node.position.sqdist(&ap.position));

                    if dist_sq < ap.connect_radius_sq {
                        // This node is within the connect radius of a node.
                        // XXX: There might be a closer node, but we use
                        // the first we find.
                        connect_node = Some(node);
                        // outside the node loop, we perform some action
                        break;
                    } else if dist_sq < nearest_distance_sq {
                        // ```node``` is within the influence of the attraction point,
                        // and it's closer than the currently closest node.
                        nearest_distance_sq = dist_sq;
                        nearest_node = Some(node);
                    }
                }

                if let Some(node) = connect_node {
                    // TODO: exchange information
                    node.send_information(ap.information);
                    match ap.connect_action {
                        ConnectAction::KillAttractor => {
                            // remove attraction point
                            self.attractors.swap_remove(ap_idx);
                            // and continue with "next" (without increasing ap_idx)
                            continue 'outer;
                        }
                        ConnectAction::DisableFor {iterations: _} => {
                            unimplemented!();
                        }
                    }
                } else if let Some(node) = nearest_node {
                    // update the force with the normalized vector towards the attraction point
                    let v = (ap.position - node.position).normalize() * ap.strength;
                    node.growth = node.growth + v;
                    node.growth_count += 1;
                }

                // go to next attractor point
                ap_idx += 1;
            }
        }

        // now create new nodes
        for i in start_index..num_nodes {
            let growth_count = self.nodes[i].growth_count;
            if growth_count > 0 {
                let growth_factor = 1.0; //((growth_count + 1) as f32).ln();
                let d = self.nodes[i].growth.normalize() * move_distance * growth_factor;
                let new_position = self.nodes[i].position + d;
                self.add_node(new_position, Some(i));

                self.nodes[i].active_lifetime -= 1;
                self.nodes[i].inactive_lifetime = self.default_inactive_lifetime; // XXX

                // and reset growth attraction forces
                self.nodes[i].growth = Zero::zero();
                self.nodes[i].growth_count = 0;
            } else {
                self.nodes[i].inactive_lifetime -= 1;
            }
        }

        // Note that nodes can oscillate, between two attraction points, so
        // it's better to stop after a certain number of iterations
        return self.nodes.len() - num_nodes;
    }
}
<commit_msg>Introduce NodeIdx<commit_after>extern crate nalgebra as na;
extern crate num;

use na::{Norm, FloatPnt, FloatVec};
use num::Zero;
use std::cmp;

/// Wraps a square distance.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct SqDist(pub f32);

impl SqDist {
    pub fn from_dist(d: f32) -> SqDist {
        SqDist(d.powi(2))
    }
}

/// What to do when a node `connects` with an attrator.
#[derive(Debug, Copy, Clone)]
pub enum ConnectAction {
    KillAttractor,
    DisableFor {
        iterations: u32,
    },
}

#[derive(Debug, Copy, Clone)]
pub struct Attractor<P, I> {
    /// The radius^2 within which it can influence a Node.
    attract_radius_sq: SqDist,

    /// If there is a node closer than the square root of
    /// this radius, the information is exchanged with the
    /// node and the ```connect_action``` is performed.
    /// This can be for example: kill the attractor,
    /// or disable it for a while.
    connect_radius_sq: SqDist,

    /// The strenght with which it influences a Node.
    strength: f32,

    /// The position of the attractor.
    pub position: P,

    /// The attractor carries a bit of information.
    /// When a node comes closer than ```connect_radius```
    /// this bit of information is exchanged.
    information: I,

    /// Action performed when a node comes closer
    /// than ```connect_radius```.
    connect_action: ConnectAction,
}

#[derive(Debug, Copy, Clone)]
struct NodeIdx(u32, u32);

struct Node<P, F> {
    /// Index of the direct parent.
    parent: NodeIdx,

    /// Index of the root node this node is associated with.
    root: NodeIdx,

    /// Number of nodes between this node and the root node.
    length: usize,

    /// The node's coordinate position.
    position: P,

    // The active_lifetime of a node is reduced every
    // time it is found being the closest node to some
    // attraction point. If it hits 0, the node
    // is no longer used.
    active_lifetime: i32,
    // The inactive_lifetime is reduce whenever a node
    // is not being found as the closest towards an
    // attraction point.
    inactive_lifetime: i32,

    growth: F,
    growth_count: u32,
}

impl<P, F> Node<P, F> {
    fn send_information(&mut self, _information: ()) {}

    fn is_root(&self) -> bool {
        // self.root == self.parent
        self.length == 0
    }
}

pub struct SpaceColonization<P, F>
    where P: FloatPnt<f32, F>,
          F: FloatVec<f32> + Zero + Copy
{
    nodes: Vec<Node<P, F>>,
    attractors: Vec<Attractor<P, ()>>,
    default_active_lifetime: i32,
    default_inactive_lifetime: i32,
    default_attract_radius_sq: SqDist,
    default_connect_radius_sq: SqDist,
}

impl<P, F> SpaceColonization<P, F>
    where P: FloatPnt<f32, F>,
          F: FloatVec<f32> + Zero + Copy
{
    pub fn new(default_active_lifetime: i32,
               default_inactive_lifetime: i32,
               default_attract_radius_sq: SqDist,
               default_connect_radius_sq: SqDist)
               -> SpaceColonization<P, F> {
        SpaceColonization {
            nodes: Vec::new(),
            attractors: Vec::new(),
            default_active_lifetime: default_active_lifetime,
            default_inactive_lifetime: default_inactive_lifetime,
            default_attract_radius_sq: default_attract_radius_sq,
            default_connect_radius_sq: default_connect_radius_sq,
        }
    }

    pub fn attractors(&self) -> &[Attractor<P, ()>] {
        &self.attractors
    }

    pub fn add_attractor(&mut self, position: P) {
        self.attractors.push(Attractor {
            attract_radius_sq: self.default_attract_radius_sq,
            connect_radius_sq: self.default_connect_radius_sq,
            strength: 1.0,
            position: position,
            information: (),
            connect_action: ConnectAction::KillAttractor,
        });
    }

    pub fn add_root_node(&mut self, position: P) {
        self.add_node(position, None);
    }

    fn get_node(&self, node_idx: NodeIdx) -> Option<&Node<P, F>> {
        self.nodes.get(node_idx.0 as usize)
    }

    fn add_node(&mut self, position: P, parent: Option<NodeIdx>) {
        let (parent, root, length) = match parent {
            Some(p) => {
                let parent_node = self.get_node(p).unwrap();
                (p, parent_node.root, parent_node.length + 1)
            }
            None => {
                // A root node has it's own index as parent and root.
                let len = self.nodes.len();
                (NodeIdx(len as u32, 0), NodeIdx(len as u32, 0), 0)
            }
        };

        self.nodes.push(Node {
            parent: parent,
            root: root,
            length: length,
            position: position,
            active_lifetime: self.default_active_lifetime,
            inactive_lifetime: self.default_inactive_lifetime,
            growth: Zero::zero(),
            growth_count: 0,
        });
    }

    pub fn iter_segments<C>(&self, callback: &mut C)
        where C: FnMut(&P, &P)
    {
        for node in self.nodes.iter() {
            if !node.is_root() {
                callback(&node.position,
                         &self.get_node(node.parent).unwrap().position);
            }
        }
    }

    pub fn iterate(&mut self, move_distance: f32, use_last_n_nodes: Option<usize>) -> usize {
        let num_nodes = self.nodes.len();
        let use_last_nodes: usize = cmp::min(num_nodes, use_last_n_nodes.unwrap_or(num_nodes));
        let start_index = num_nodes - use_last_nodes;

        {
            let nodes = &mut self.nodes[start_index..];

            // for each attraction_point, find the nearest node that it influences
            let mut ap_idx = 0;
            'outer: while ap_idx < self.attractors.len() {
                let ap = self.attractors[ap_idx];

                // find the node nearest to the `ap` attraction point
                let mut nearest_node: Option<&mut Node<_, _>> = None;
                let mut nearest_distance_sq = ap.attract_radius_sq;
                let mut connect_node: Option<&mut Node<_, _>> = None;
                for node in nodes.iter_mut() {
                    if node.inactive_lifetime <= 0 || node.active_lifetime <= 0 {
                        // The node has become inactive
                        continue;
                    }

                    let dist_sq = SqDist(node.position.sqdist(&ap.position));

                    if dist_sq < ap.connect_radius_sq {
                        // This node is within the connect radius of a node.
                        // XXX: There might be a closer node, but we use
                        // the first we find.
                        connect_node = Some(node);
                        // outside the node loop, we perform some action
                        break;
                    } else if dist_sq < nearest_distance_sq {
                        // ```node``` is within the influence of the attraction point,
                        // and it's closer than the currently closest node.
                        nearest_distance_sq = dist_sq;
                        nearest_node = Some(node);
                    }
                }

                if let Some(node) = connect_node {
                    // TODO: exchange information
                    node.send_information(ap.information);
                    match ap.connect_action {
                        ConnectAction::KillAttractor => {
                            // remove attraction point
                            self.attractors.swap_remove(ap_idx);
                            // and continue with "next" (without increasing ap_idx)
                            continue 'outer;
                        }
                        ConnectAction::DisableFor {iterations: _} => {
                            unimplemented!();
                        }
                    }
                } else if let Some(node) = nearest_node {
                    // update the force with the normalized vector towards the attraction point
                    let v = (ap.position - node.position).normalize() * ap.strength;
                    node.growth = node.growth + v;
                    node.growth_count += 1;
                }

                // go to next attractor point
                ap_idx += 1;
            }
        }

        // now create new nodes
        for i in start_index..num_nodes {
            let growth_count = self.nodes[i].growth_count;
            if growth_count > 0 {
                let growth_factor = 1.0; //((growth_count + 1) as f32).ln();
                let d = self.nodes[i].growth.normalize() * move_distance * growth_factor;
                let new_position = self.nodes[i].position + d;
                self.add_node(new_position, Some(NodeIdx(i as u32, 0)));

                self.nodes[i].active_lifetime -= 1;
                self.nodes[i].inactive_lifetime = self.default_inactive_lifetime; // XXX

                // and reset growth attraction forces
                self.nodes[i].growth = Zero::zero();
                self.nodes[i].growth_count = 0;
            } else {
                self.nodes[i].inactive_lifetime -= 1;
            }
        }

        // Note that nodes can oscillate, between two attraction points, so
        // it's better to stop after a certain number of iterations
        return self.nodes.len() - num_nodes;
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove trailing whitespaces<commit_after><|endoftext|>


<commit_before>extern crate libc;

mod ffi;

use libc::c_char;
use std::ffi::*;
use ffi::*;

/// Result of opening a file dialog
pub enum NFDResult {
    /// User pressed okay. `String` is the file path selected
    Okay(String),
    /// User pressed cancel
    Cancel,
    /// Program error. `String` is the error description
    Error(String),
}

enum DialogType {
    SingleFile,
    SaveFile
}

/// Open single file dialog
#[inline(always)]
pub fn open_file_dialog(filter_list: &str, default_path: &str) -> NFDResult {
    open_dialog(filter_list, default_path, &DialogType::SingleFile)
}

/// Open save dialog
#[inline(always)]
pub fn open_save_dialog(filter_list: &str, default_path: &str) -> NFDResult {
    open_dialog(filter_list, default_path, &DialogType::SaveFile)
}

fn open_dialog(filter_list: &str, default_path: &str, dialog_type: &DialogType) -> NFDResult {

    let mut final_cstring = CString::new("").unwrap();
    let out_path = CString::new("").unwrap().into_raw() as *mut *mut c_char;
    let result: nfdresult_t;

    unsafe {
        result = match dialog_type {
            &DialogType::SingleFile => {
                NFD_OpenDialog(
                CString::new(filter_list).unwrap().as_ptr(),
                CString::new(default_path).unwrap().as_ptr(),
                out_path)
            },

            &DialogType::SaveFile => {
                NFD_SaveDialog(
                CString::new(filter_list).unwrap().as_ptr(),
                CString::new(default_path).unwrap().as_ptr(),
                out_path)
            },
        };

        match result {
            nfdresult_t::NFD_OKAY => {
                final_cstring = CString::from_raw(*out_path);
            },
            nfdresult_t::NFD_ERROR => {
                final_cstring = CStr::from_ptr(NFD_GetError()).to_owned();
            }
            _ => {},
        }
    }

    let final_string = final_cstring.to_str().unwrap().to_string();

    match result {
        nfdresult_t::NFD_OKAY => NFDResult::Okay(final_string),
        nfdresult_t::NFD_CANCEL => NFDResult::Cancel,
        nfdresult_t::NFD_ERROR => NFDResult::Error(final_string)
    }
}
<commit_msg>Refactor code in lib.rs<commit_after>extern crate libc;

mod ffi;

use ffi::*;
use libc::c_char;
use std::ffi::*;

/// Result of opening a file dialog
pub enum NFDResult {
    /// User pressed okay. `String` is the file path selected
    Okay(String),
    /// User pressed cancel
    Cancel,
    /// Program error. `String` is the error description
    Error(String),
}

enum DialogType {
    SingleFile,
    SaveFile
}

/// Open single file dialog
#[inline(always)]
pub fn open_file_dialog(filter_list: &str, default_path: &str) -> NFDResult {
    open_dialog(filter_list, default_path, &DialogType::SingleFile)
}

/// Open save dialog
#[inline(always)]
pub fn open_save_dialog(filter_list: &str, default_path: &str) -> NFDResult {
    open_dialog(filter_list, default_path, &DialogType::SaveFile)
}

fn open_dialog(filter_list: &str, default_path: &str, dialog_type: &DialogType) -> NFDResult {
    let result: nfdresult_t;
    let result_cstring;

    let filter_list_cstring = CString::new(filter_list).unwrap();
    let default_path_cstring = CString::new(default_path).unwrap();
    let out_path = CString::new("").unwrap().into_raw() as *mut *mut c_char;

    unsafe {
        result = match dialog_type {
            &DialogType::SingleFile => {
                NFD_OpenDialog(filter_list_cstring.as_ptr(), default_path_cstring.as_ptr(), out_path)
            },

            &DialogType::SaveFile => {
                NFD_SaveDialog(filter_list_cstring.as_ptr(), default_path_cstring.as_ptr(), out_path)
            },
        };

        result_cstring = match result {
            nfdresult_t::NFD_OKAY => CString::from_raw(*out_path),
            nfdresult_t::NFD_ERROR => CStr::from_ptr(NFD_GetError()).to_owned(),
            _ => CString::new("").unwrap()
        }
    }

    let result_string = result_cstring.to_str().unwrap().to_string();

    match result {
        nfdresult_t::NFD_OKAY => NFDResult::Okay(result_string),
        nfdresult_t::NFD_CANCEL => NFDResult::Cancel,
        nfdresult_t::NFD_ERROR => NFDResult::Error(result_string)
    }
}
<|endoftext|>


<commit_before>pub mod rk4;

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        let _ = rk4::solver(|t: &f32, _: &Vec<f32>| -> Vec<f32> {
            vec![2.*t]
        }, vec![0.], &[0., 0.], 1.0);
    }
}
<commit_msg>Start work on an alternative experimental syntax<commit_after>pub mod rk4;

use std::ops::Add;

pub enum Method {
    RK2,
    RK4,
}

/**
```
use ode::{Method, Solver};

let ini_cond: Vec<f32> = vec![1., 2.];

// simple config
Solver::new(ini_cond.clone(), |t: &f32, _: &Vec<f32>| vec![2.*t] )
    .method(Method::RK4)
    .run();

// complex config
let mut s = Solver::new(ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t] );
s.method(Method::RK4);
let (times, pos) = s.run();
```
*/
pub struct Solver<T, F>
    where T: From<f32>,
          F: Fn(&T, &Vec<T>) -> Vec<T> {
    method: Method,
    weights: Vec<T>,
    weight_sum: T,
    step: T,
    initial_conditions: Vec<T>,
    function: F,
}

impl<T, F> Solver<T, F>
    where T: Add<Output = T> + Clone + From<u8> + From<f32>,
          F: Fn(&T, &Vec<T>) -> Vec<T> {

    pub fn new(initial_conditions: Vec<T>, function: F) -> Solver<T, F> {
        Solver {
            method: Method::RK4,
            weights: vec![T::from(1), T::from(2), T::from(2), T::from(1)],
            weight_sum: T::from(6),
            step: T::from(10e-3),
            initial_conditions: initial_conditions,
            function: function,
        }
    }

    /**
    Select the desired algorithm to solve the givem problem, also changing the
    default weights (see `change_weight()` for more details) applyed in each
    case; default values are:

    - `Method::RK2`: `vec![T::from(1), T::from(1)],`
    - `Method::RK4`: `vec![T::from(1), T::from(2), T::from(2), T::from(1)],`

    Defaults to `Method::RK4`.
    */
    pub fn method(&mut self, new_method: Method) -> &mut Solver<T, F> {
        match new_method {
            Method::RK2 => self.weights = vec![T::from(1), T::from(1)],
            Method::RK4 => self.weights = vec![T::from(1), T::from(2),
                                               T::from(2), T::from(1)],
        }

        self.weight_sum = self.weights.iter()
            .fold(T::from(0), |sum, i| sum + i.clone());
        self.method = new_method;
        self
    }

    /**
    Modify the default weighting applyed to each intermidiate point. Notice
    that, when changing
    */
    pub fn change_weight(&mut self, new_weights: Vec<T>) -> &mut Solver<T, F> {
        self.weights = new_weights;
        self
    }

    /**
    Validates the data passed to the solver. This is tipically called by `run()`
    before attempting to solve the passed function.
    */
    pub fn validate(&self) {
        // make sure the weights match with the method
        assert_eq!(self.weights.len(),
                   match self.method {
                       Method::RK2 => 2,
                       Method::RK4 => 4,
                   });
    }

    /**
    Check and run the solver, returning the results of the calculation.
    */
    pub fn run(&self) -> (Vec<T>, Vec<Vec<T>>) {
        self.validate();

        (Vec::new(), Vec::new())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        let _ = rk4::solver(|t: &f32, _: &Vec<f32>| -> Vec<f32> {
            vec![2.*t]
        }, vec![0.], &[0., 0.], 1.0);
    }
}
<|endoftext|>


<commit_before>#![warn(missing_docs)]

//! A `Pinboard` is a shared, mutable, eventually consistent, lock-free data-structure.  This
//! allows multiple threads to communicate in a decoupled way by publishing data to the pinboard
//! which other threads can then read in an eventually consistent way.
//!
//! This is not a silver bullet though, there are various limitations of `Pinboard` that trade off
//! the nice behaviour described above.
//!
//! * Eventual consistency:
//!     * Writes from one thread are not guaranteed to be seen by reads from another thread
//!     * Writes from one thread can overwrite writes from another thread
//! * No in-place mutation:
//!     * The only write primitive completely overwrites the data on the `Pinboard`
//! * Requires `Clone`:
//!     * All reads return a clone of the data, decoupling the lifetime of the read value from the
//!     data stored in the global reference.

extern crate crossbeam;

use crossbeam::mem::epoch::{Atomic, Owned, pin};
use std::sync::atomic::Ordering::*;

use std::ops::Deref;

/// An instance of a `Pinboard`, holds a shared, mutable, eventually-consistent reference to a `T`.
pub struct Pinboard<T: Clone>(Atomic<T>);

impl<T: Clone> Pinboard<T> {
    /// Create a new `Pinboard` instance holding the given value.
    pub fn new(t: T) -> Pinboard<T> {
        let t = Owned::new(t);
        let p = Pinboard::default();
        p.0.store(Some(t), Release);
        p
    }

    /// Update the value stored in the `Pinboard`.
    pub fn set(&self, t: T) {
        let guard = pin();
        let t = Owned::new(t);
        if let Some(t) = self.0.swap(Some(t), Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Clear out the `Pinboard` so its no longer holding any data.
    pub fn clear(&self) {
        let guard = pin();
        if let Some(t) = self.0.swap(None, Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    pub fn read(&self) -> Option<T> {
        let guard = pin();
        let t = self.0.load(Acquire, &guard);
        t.map(|t| -> &T { t.deref() }).cloned()
    }
}

impl<T: Clone> Default for Pinboard<T> {
    fn default() -> Pinboard<T> {
        Pinboard(Atomic::null())
    }
}

impl<T: Clone> Drop for Pinboard<T> {
    fn drop(&mut self) {
        // Make sure any stored data is marked for deletion
        self.clear();
    }
}

/// An wrapper around a `Pinboard` which provides the guarantee it is never empty.
pub struct NonEmptyPinboard<T: Clone>(Pinboard<T>);

impl<T: Clone> NonEmptyPinboard<T> {
    /// Create a new `NonEmptyPinboard` instance holding the given value.
    pub fn new(t: T) -> NonEmptyPinboard<T> {
        NonEmptyPinboard(Pinboard::new(t))
    }

    /// Update the value stored in the `NonEmptyPinboard`.
    #[inline]
    pub fn set(&self, t: T) {
        self.0.set(t)
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    #[inline]
    pub fn read(&self) -> T {
        // Unwrap the option returned by the inner `Pinboard`. This will never panic, because it's
        // impossible for this `Pinboard` to be empty (though it's not possible to prove this to the
        // compiler).
        match self.0.read() {
            Some(t) => t,
            None => unreachable!("Inner pointer was unexpectedly null"),
        }
    }
}

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

    fn consume<T: Clone + Display>(t: &Pinboard<T>) {
        loop {
            match t.read() {
                Some(_) => {}
                None => break,
            }
            std::thread::sleep(std::time::Duration::from_millis(1));
        }
    }

    fn produce(t: &Pinboard<u32>) {
        for i in 1..100 {
            t.set(i);
            std::thread::sleep(std::time::Duration::from_millis(2));
        }
        t.clear();
    }

    #[test]
    fn it_works() {
        let t = Pinboard::<u32>::default();
        assert_eq!(None, t.read());
        t.set(3);
        assert_eq!(Some(3), t.read());
        t.clear();
        assert_eq!(None, t.read());
    }

    #[test]
    fn single_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn multi_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn single_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn multi_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn non_empty_pinboard() {
        let t = NonEmptyPinboard::<u32>::new(3);
        assert_eq!(3, t.read());
        t.set(4);
        assert_eq!(4, t.read());
    }
}
<commit_msg>Add various std::fmt impl clauses<commit_after>#![warn(missing_docs)]

//! A `Pinboard` is a shared, mutable, eventually consistent, lock-free data-structure.  This
//! allows multiple threads to communicate in a decoupled way by publishing data to the pinboard
//! which other threads can then read in an eventually consistent way.
//!
//! This is not a silver bullet though, there are various limitations of `Pinboard` that trade off
//! the nice behaviour described above.
//!
//! * Eventual consistency:
//!     * Writes from one thread are not guaranteed to be seen by reads from another thread
//!     * Writes from one thread can overwrite writes from another thread
//! * No in-place mutation:
//!     * The only write primitive completely overwrites the data on the `Pinboard`
//! * Requires `Clone`:
//!     * All reads return a clone of the data, decoupling the lifetime of the read value from the
//!     data stored in the global reference.

extern crate crossbeam;

use crossbeam::mem::epoch::{Atomic, Owned, pin};
use std::sync::atomic::Ordering::*;

use std::ops::Deref;

/// An instance of a `Pinboard`, holds a shared, mutable, eventually-consistent reference to a `T`.
pub struct Pinboard<T: Clone>(Atomic<T>);

impl<T: Clone> Pinboard<T> {
    /// Create a new `Pinboard` instance holding the given value.
    pub fn new(t: T) -> Pinboard<T> {
        let t = Owned::new(t);
        let p = Pinboard::default();
        p.0.store(Some(t), Release);
        p
    }

    /// Update the value stored in the `Pinboard`.
    pub fn set(&self, t: T) {
        let guard = pin();
        let t = Owned::new(t);
        if let Some(t) = self.0.swap(Some(t), Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Clear out the `Pinboard` so its no longer holding any data.
    pub fn clear(&self) {
        let guard = pin();
        if let Some(t) = self.0.swap(None, Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    pub fn read(&self) -> Option<T> {
        let guard = pin();
        let t = self.0.load(Acquire, &guard);
        t.map(|t| -> &T { t.deref() }).cloned()
    }
}

impl<T: Clone> Default for Pinboard<T> {
    fn default() -> Pinboard<T> {
        Pinboard(Atomic::null())
    }
}

impl<T: Clone> Drop for Pinboard<T> {
    fn drop(&mut self) {
        // Make sure any stored data is marked for deletion
        self.clear();
    }
}

/// An wrapper around a `Pinboard` which provides the guarantee it is never empty.
pub struct NonEmptyPinboard<T: Clone>(Pinboard<T>);

impl<T: Clone> NonEmptyPinboard<T> {
    /// Create a new `NonEmptyPinboard` instance holding the given value.
    pub fn new(t: T) -> NonEmptyPinboard<T> {
        NonEmptyPinboard(Pinboard::new(t))
    }

    /// Update the value stored in the `NonEmptyPinboard`.
    #[inline]
    pub fn set(&self, t: T) {
        self.0.set(t)
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    #[inline]
    pub fn read(&self) -> T {
        // Unwrap the option returned by the inner `Pinboard`. This will never panic, because it's
        // impossible for this `Pinboard` to be empty (though it's not possible to prove this to the
        // compiler).
        match self.0.read() {
            Some(t) => t,
            None => unreachable!("Inner pointer was unexpectedly null"),
        }
    }
}

macro_rules! debuggable {
    ($struct:ident, $trait:ident) => {
        impl<T: Clone> ::std::fmt::$trait for $struct<T> where T: ::std::fmt::$trait {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
                write!(f, "{}(", stringify!($struct))?;
                ::std::fmt::$trait::fmt(&self.read(), f)?;
                write!(f, ")")
            }
        }
    }
}

debuggable!(Pinboard, Debug);
debuggable!(NonEmptyPinboard, Debug);
debuggable!(NonEmptyPinboard, Binary);
debuggable!(NonEmptyPinboard, Display);
debuggable!(NonEmptyPinboard, LowerExp);
debuggable!(NonEmptyPinboard, LowerHex);
debuggable!(NonEmptyPinboard, Octal);
debuggable!(NonEmptyPinboard, Pointer);
debuggable!(NonEmptyPinboard, UpperExp);
debuggable!(NonEmptyPinboard, UpperHex);

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

    fn consume<T: Clone + Display>(t: &Pinboard<T>) {
        loop {
            match t.read() {
                Some(_) => {}
                None => break,
            }
            std::thread::sleep(std::time::Duration::from_millis(1));
        }
    }

    fn produce(t: &Pinboard<u32>) {
        for i in 1..100 {
            t.set(i);
            std::thread::sleep(std::time::Duration::from_millis(2));
        }
        t.clear();
    }

    #[test]
    fn it_works() {
        let t = Pinboard::<u32>::default();
        assert_eq!(None, t.read());
        t.set(3);
        assert_eq!(Some(3), t.read());
        t.clear();
        assert_eq!(None, t.read());
    }

    #[test]
    fn single_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn multi_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn single_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn multi_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn non_empty_pinboard() {
        let t = NonEmptyPinboard::<u32>::new(3);
        assert_eq!(3, t.read());
        t.set(4);
        assert_eq!(4, t.read());
    }
}
<|endoftext|>


<commit_before>mod traits;
pub use self::traits::*;

#[macro_export]
macro_rules! impl_op {
    (($lhs:path) + ($rhs:path) = ($out:path)) => (_impl_binary_op_internal!(Add, add, $lhs, $rhs, $out););
    (($lhs:path) + ($rhs:path) = ($out:path), $fn:path) => (_impl_binary_op_internal!(Add, add, $lhs, $rhs, $out, $fn););
    (($lhs:path) - ($rhs:path) = ($out:path)) => (_impl_binary_op_internal!(Sub, sub, $lhs, $rhs, $out););
    (($lhs:path) - ($rhs:path) = ($out:path), $fn:path) => (_impl_binary_op_internal!(Sub, sub, $lhs, $rhs, $out, $fn););
    (($lhs:path) * ($rhs:path) = ($out:path)) => (_impl_binary_op_internal!(Mul, mul, $lhs, $rhs, $out););
    (($lhs:path) * ($rhs:path) = ($out:path), $fn:path) => (_impl_binary_op_internal!(Mul, mul, $lhs, $rhs, $out, $fn););
    (($lhs:path) / ($rhs:path) = ($out:path)) => (_impl_binary_op_internal!(Div, div, $lhs, $rhs, $out););
    (($lhs:path) / ($rhs:path) = ($out:path), $fn:path) => (_impl_binary_op_internal!(Div, div, $lhs, $rhs, $out, $fn););
    (($lhs:path) & ($rhs:path) = ($out:path)) => (_impl_binary_op_internal!(BitAnd, bitand, $lhs, $rhs, $out););
    (($lhs:path) & ($rhs:path) = ($out:path), $fn:path) => (_impl_binary_op_internal!(BitAnd, bitand, $lhs, $rhs, $out, $fn););
    (($lhs:path) | ($rhs:path) = ($out:path)) => (_impl_binary_op_internal!(BitOr, bitor, $lhs, $rhs, $out););
    (($lhs:path) | ($rhs:path) = ($out:path), $fn:path) => (_impl_binary_op_internal!(BitOr, bitor, $lhs, $rhs, $out, $fn););
    (($lhs:path) ^ ($rhs:path) = ($out:path)) => (_impl_binary_op_internal!(BitXor, bitxor, $lhs, $rhs, $out););
    (($lhs:path) ^ ($rhs:path) = ($out:path), $fn:path) => (_impl_binary_op_internal!(BitXor, bitxor, $lhs, $rhs, $out, $fn););
    (($lhs:path) % ($rhs:path) = ($out:path)) => (_impl_binary_op_internal!(Rem, rem, $lhs, $rhs, $out););
    (($lhs:path) % ($rhs:path) = ($out:path), $fn:path) => (_impl_binary_op_internal!(Rem, rem, $lhs, $rhs, $out, $fn););
    (($lhs:path) << ($rhs:path) = ($out:path)) => (_impl_binary_op_internal!(Shl, shl, $lhs, $rhs, $out););
    (($lhs:path) << ($rhs:path) = ($out:path), $fn:path) => (_impl_binary_op_internal!(Shl, shl, $lhs, $rhs, $out, $fn););
    (($lhs:path) >> ($rhs:path) = ($out:path)) => (_impl_binary_op_internal!(Shr, shr, $lhs, $rhs, $out););
    (($lhs:path) >> ($rhs:path) = ($out:path), $fn:path) => (_impl_binary_op_internal!(Shr, shr, $lhs, $rhs, $out, $fn););
}

#[macro_export]
macro_rules! _impl_binary_op_internal {
    ($ops_trait:ident, $ops_fn:ident, $lhs:ty, $rhs:ty, $out:ty) => (_impl_binary_op_internal!($ops_trait, $ops_fn, $lhs, $rhs, $out, impl_ops::$ops_trait::$ops_fn););
    ($ops_trait:ident, $ops_fn:ident, $lhs:ty, $rhs:ty, $out:ty, $fn:path) => (
        impl ops::$ops_trait<$rhs> for $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: $rhs) -> Self::Output {
                $fn(&self, &rhs)
            }
        }

        impl<'a> ops::$ops_trait<&'a $rhs> for $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: &'a $rhs) -> Self::Output {
                $fn(&self, rhs)
            }
        }

        impl<'a> ops::$ops_trait<$rhs> for &'a $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: $rhs) -> Self::Output {
                $fn(self, &rhs)
            }
        }

        impl<'a> ops::$ops_trait<&'a $rhs> for &'a $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: &'a $rhs) -> Self::Output {
                $fn(self, rhs)
            }
        }
    )
}
<commit_msg>much cleaner binary op macros<commit_after>mod traits;
pub use self::traits::*;

#[macro_export]
macro_rules! impl_op {
    (($lhs:path) $op:tt ($rhs:path) = ($out:path)) => (_parse_binary_op!($op, $lhs, $rhs, $out););
    (($lhs:path) $op:tt ($rhs:path) = ($out:path), $fn:path) => (_parse_binary_op!($op, $lhs, $rhs, $out, $fn););
}

#[macro_export]
macro_rules! _parse_binary_op {
    (+, $($t:tt)+) => (_impl_binary_op_internal!(Add, add, $($t)+););
    (-, $($t:tt)+) => (_impl_binary_op_internal!(Sub, sub, $($t)+););
    (*, $($t:tt)+) => (_impl_binary_op_internal!(Mul, mull, $($t)+););
    (/, $($t:tt)+) => (_impl_binary_op_internal!(Div, div, $($t)+););
    (&, $($t:tt)+) => (_impl_binary_op_internal!(BitAnd, bitand, $($t)+););
    (|, $($t:tt)+) => (_impl_binary_op_internal!(BitOr, bitor, $($t)+););
    (^, $($t:tt)+) => (_impl_binary_op_internal!(BitXor, bitxor, $($t)+););
    (%, $($t:tt)+) => (_impl_binary_op_internal!(Rem, rem, $($t)+););
    (<<, $($t:tt)+) => (_impl_binary_op_internal!(Shl, shl, $($t)+););
    (>>, $($t:tt)+) => (_impl_binary_op_internal!(Shr, shr, $($t)+););
}

#[macro_export]
macro_rules! _impl_binary_op_internal {
    ($ops_trait:ident, $ops_fn:ident, $lhs:ty, $rhs:ty, $out:ty) => (_impl_binary_op_internal!($ops_trait, $ops_fn, $lhs, $rhs, $out, impl_ops::$ops_trait::$ops_fn););
    ($ops_trait:ident, $ops_fn:ident, $lhs:ty, $rhs:ty, $out:ty, $fn:path) => (
        impl ops::$ops_trait<$rhs> for $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: $rhs) -> Self::Output {
                $fn(&self, &rhs)
            }
        }

        impl<'a> ops::$ops_trait<&'a $rhs> for $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: &'a $rhs) -> Self::Output {
                $fn(&self, rhs)
            }
        }

        impl<'a> ops::$ops_trait<$rhs> for &'a $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: $rhs) -> Self::Output {
                $fn(self, &rhs)
            }
        }

        impl<'a> ops::$ops_trait<&'a $rhs> for &'a $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: &'a $rhs) -> Self::Output {
                $fn(self, rhs)
            }
        }
    )
}
<|endoftext|>


<commit_before>#![crate_name = "spinlock"]
#![experimental]
#![crate_type = "lib"]
#![feature(unsafe_destructor)]
#![warn(missing_docs)]

#![no_std]

//! This crate provides a thread-safe data container.
//!
//! # Description
//!
//! This structure behaves a lot like a normal Mutex. There are some differences:
//!
//! - It may be used outside the runtime.
//!   - A normal mutex will fail when used without the runtime, this will just lock
//!   - When the runtime is present, it will call the deschedule function when appropriate
//! - No lock poisoning. When a fail occurs when the lock is held, no guarantees are made
//!
//! When calling rust functions from bare threads, such as C `pthread`s, this lock will be very
//! helpfull. In other cases however, you are encouraged to use the locks from the standard
//! library.
//!
//! # Simple example
//!
//! ```
//! use spinlock::Spinlock;
//! let spinlock = Spinlock::new(0);
//!
//! // Modify the data
//! {
//!     let mut data = spinlock.lock();
//!     *data = 2;
//! }
//!
//! // Read the data
//! let answer =
//! {
//!     let data = spinlock.lock();
//!     *data
//! };
//!
//! assert_eq!(answer, 2);
//! ```
//!
//! # Thread-safety example
//!
//! ```
//! use spinlock::Spinlock;
//! use std::sync::{Arc, Barrier};
//!
//! let numthreads = 1000;
//! let spinlock = Arc::new(Spinlock::new(0));
//!
//! // We use a barrier to ensure the readout happens after all writing
//! let barrier = Arc::new(Barrier::new(numthreads + 1));
//!
//! for _ in (0..numthreads)
//! {
//!     let my_barrier = barrier.clone();
//!     let my_lock = spinlock.clone();
//!     std::thread::Thread::spawn(move||
//!     {
//!         let mut guard = my_lock.lock();
//!         *guard += 1;
//!
//!         // Release the lock to prevent a deadlock
//!         drop(guard);
//!         my_barrier.wait();
//!     });
//! }
//!
//! barrier.wait();
//!
//! let answer = { *spinlock.lock() };
//! assert_eq!(answer, numthreads);
//! ```

#[cfg(test)] extern crate std;
extern crate core;

use core::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT};
use core::cell::UnsafeCell;
use core::marker::Sync;
use core::ops::{Drop, Deref, DerefMut};

/// A wrapper for the data giving access in a thread-safe manner
pub struct Spinlock<T>
{
    lock: AtomicBool,
    data: UnsafeCell<T>,
}

/// A guard to which the protected data can be accessed
///
/// When the guard falls out of scope it will release the lock.
#[experimental]
pub struct SpinlockGuard<'a, T:'a>
{
    lock: &'a AtomicBool,
    data: &'a mut T,
}

unsafe impl<T> Sync for Spinlock<T> {}

/// A Spinlock which may be used statically.
///
/// ```
/// use spinlock::{StaticSpinlock, STATIC_SPINLOCK_INIT};
///
/// static SPLCK: StaticSpinlock = STATIC_SPINLOCK_INIT;
///
/// fn demo() {
///     let lock = SPLCK.lock();
///     // do something with lock
///     drop(lock);
/// }
/// ```
pub type StaticSpinlock = Spinlock<()>;

/// A initializer for StaticSpinlock, containing no data.
pub const STATIC_SPINLOCK_INIT: StaticSpinlock = Spinlock {
    lock: ATOMIC_BOOL_INIT,
    data: UnsafeCell { value: () },
};

#[deprecated = "renamed to STATIC_SPINLOCK_INIT"]
pub const INIT_STATIC_SPINLOCK: StaticSpinlock = STATIC_SPINLOCK_INIT;

impl<T> Spinlock<T>
{
    /// Creates a new spinlock wrapping the supplied data.
    #[unstable]
    pub fn new(user_data: T) -> Spinlock<T>
    {
        Spinlock
        {
            lock: ATOMIC_BOOL_INIT,
            data: UnsafeCell::new(user_data),
        }
    }

    fn obtain_lock(&self)
    {
        while self.lock.compare_and_swap(false, true, Ordering::SeqCst) != false
        {
            // Do nothing
        }
    }

    /// Locks the spinlock and returns a guard.
    ///
    /// The returned value may be dereferenced for data access
    /// and the lock will be dropped when the guard falls out of scope.
    ///
    /// ```
    /// let mylock = spinlock::Spinlock::new(0u);
    /// {
    ///     let mut data = mylock.lock();
    ///     // The lock is now locked and the data can be accessed
    ///     *data += 1;
    /// }
    /// // The lock is dropped
    /// ```
    pub fn lock(&self) -> SpinlockGuard<T>
    {
        self.obtain_lock();
        SpinlockGuard
        {
            lock: &self.lock,
            data: unsafe { &mut *self.data.get() },
        }
    }
}

impl<'a, T> Deref for SpinlockGuard<'a, T>
{
    type Target = T;
    fn deref<'b>(&'b self) -> &'b T { &*self.data }
}

impl<'a, T> DerefMut for SpinlockGuard<'a, T>
{
    fn deref_mut<'b>(&'b mut self) -> &'b mut T { &mut *self.data }
}

#[unsafe_destructor]
impl<'a, T> Drop for SpinlockGuard<'a, T>
{
    /// The dropping of the SpinlockGuard will release the lock it was created from.
    fn drop(&mut self)
    {
        self.lock.store(false, Ordering::SeqCst);
    }
}
<commit_msg>Fix some stability issues<commit_after>#![crate_type = "lib"]
#![feature(unsafe_destructor)]
#![warn(missing_docs)]
#![allow(unstable)]

#![no_std]

//! This crate provides a thread-safe data container.
//!
//! # Description
//!
//! This structure behaves a lot like a normal Mutex. There are some differences:
//!
//! - It may be used outside the runtime.
//!   - A normal mutex will fail when used without the runtime, this will just lock
//!   - When the runtime is present, it will call the deschedule function when appropriate
//! - No lock poisoning. When a fail occurs when the lock is held, no guarantees are made
//!
//! When calling rust functions from bare threads, such as C `pthread`s, this lock will be very
//! helpfull. In other cases however, you are encouraged to use the locks from the standard
//! library.
//!
//! # Simple example
//!
//! ```
//! use spinlock::Spinlock;
//! let spinlock = Spinlock::new(0);
//!
//! // Modify the data
//! {
//!     let mut data = spinlock.lock();
//!     *data = 2;
//! }
//!
//! // Read the data
//! let answer =
//! {
//!     let data = spinlock.lock();
//!     *data
//! };
//!
//! assert_eq!(answer, 2);
//! ```
//!
//! # Thread-safety example
//!
//! ```
//! use spinlock::Spinlock;
//! use std::sync::{Arc, Barrier};
//!
//! let numthreads = 1000;
//! let spinlock = Arc::new(Spinlock::new(0));
//!
//! // We use a barrier to ensure the readout happens after all writing
//! let barrier = Arc::new(Barrier::new(numthreads + 1));
//!
//! for _ in (0..numthreads)
//! {
//!     let my_barrier = barrier.clone();
//!     let my_lock = spinlock.clone();
//!     std::thread::Thread::spawn(move||
//!     {
//!         let mut guard = my_lock.lock();
//!         *guard += 1;
//!
//!         // Release the lock to prevent a deadlock
//!         drop(guard);
//!         my_barrier.wait();
//!     });
//! }
//!
//! barrier.wait();
//!
//! let answer = { *spinlock.lock() };
//! assert_eq!(answer, numthreads);
//! ```

#[cfg(test)] extern crate std;
extern crate core;

use core::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT};
use core::cell::UnsafeCell;
use core::marker::Sync;
use core::ops::{Drop, Deref, DerefMut};

/// A wrapper for the data giving access in a thread-safe manner
pub struct Spinlock<T>
{
    lock: AtomicBool,
    data: UnsafeCell<T>,
}

/// A guard to which the protected data can be accessed
///
/// When the guard falls out of scope it will release the lock.
pub struct SpinlockGuard<'a, T:'a>
{
    lock: &'a AtomicBool,
    data: &'a mut T,
}

unsafe impl<T> Sync for Spinlock<T> {}

/// A Spinlock which may be used statically.
///
/// ```
/// use spinlock::{StaticSpinlock, STATIC_SPINLOCK_INIT};
///
/// static SPLCK: StaticSpinlock = STATIC_SPINLOCK_INIT;
///
/// fn demo() {
///     let lock = SPLCK.lock();
///     // do something with lock
///     drop(lock);
/// }
/// ```
pub type StaticSpinlock = Spinlock<()>;

/// A initializer for StaticSpinlock, containing no data.
pub const STATIC_SPINLOCK_INIT: StaticSpinlock = Spinlock {
    lock: ATOMIC_BOOL_INIT,
    data: UnsafeCell { value: () },
};

#[deprecated = "renamed to STATIC_SPINLOCK_INIT"]
pub const INIT_STATIC_SPINLOCK: StaticSpinlock = STATIC_SPINLOCK_INIT;

impl<T> Spinlock<T>
{
    /// Creates a new spinlock wrapping the supplied data.
    pub fn new(user_data: T) -> Spinlock<T>
    {
        Spinlock
        {
            lock: ATOMIC_BOOL_INIT,
            data: UnsafeCell::new(user_data),
        }
    }

    fn obtain_lock(&self)
    {
        while self.lock.compare_and_swap(false, true, Ordering::SeqCst) != false
        {
            // Do nothing
        }
    }

    /// Locks the spinlock and returns a guard.
    ///
    /// The returned value may be dereferenced for data access
    /// and the lock will be dropped when the guard falls out of scope.
    ///
    /// ```
    /// let mylock = spinlock::Spinlock::new(0u);
    /// {
    ///     let mut data = mylock.lock();
    ///     // The lock is now locked and the data can be accessed
    ///     *data += 1;
    /// }
    /// // The lock is dropped
    /// ```
    pub fn lock(&self) -> SpinlockGuard<T>
    {
        self.obtain_lock();
        SpinlockGuard
        {
            lock: &self.lock,
            data: unsafe { &mut *self.data.get() },
        }
    }
}

impl<'a, T> Deref for SpinlockGuard<'a, T>
{
    type Target = T;
    fn deref<'b>(&'b self) -> &'b T { &*self.data }
}

impl<'a, T> DerefMut for SpinlockGuard<'a, T>
{
    fn deref_mut<'b>(&'b mut self) -> &'b mut T { &mut *self.data }
}

#[unsafe_destructor]
impl<'a, T> Drop for SpinlockGuard<'a, T>
{
    /// The dropping of the SpinlockGuard will release the lock it was created from.
    fn drop(&mut self)
    {
        self.lock.store(false, Ordering::SeqCst);
    }
}
<|endoftext|>


<commit_before>/*!

A basic library for finding primes, providing a basic Iterator over all primes.
It is not as fast as `slow_primes`, but it is meant to be easy to use!

The simplest usage is simply to create an `Iterator`:

```
use primes::PrimeSet;

let mut pset = PrimeSet::new();

for (ix, n) in pset.iter().enumerate().take(10) {
    println!("Prime {}: {}", ix, n);
}
```

This library provides methods for generating primes, testing whether a number
is prime, and factorizing numbers. Most methods generate primes lazily, so
only enough primes will be generated for the given test, and primes are cached
for later use.

To use, see `PrimeSet`, a class which handles the Sieve and has multiple
methods for iterating over primes.

This also provides a few functions unconnected to `PrimeSet`, which will be
faster for the first case, but slower in the long term as they do not use any
caching of primes.

[*Source*](https://github.com/wackywendell/primes)

# Example: Find the millionth prime

```
use primes::PrimeSet;

let mut pset = PrimeSet::new();
let (ix, n) = pset.find(1_000_000);

println!("Prime {}: {}", ix, n);
```

# Example: Find the first ten primes *after* the thousandth prime
```
use primes::PrimeSet;

let mut pset = PrimeSet::new();
for (ix, n) in pset.iter().enumerate().skip(1_000).take(10) {
    println!("Prime {}: {}", ix, n);
}
```

# Example: Find the first prime greater than 1000
```
use primes::PrimeSet;

let mut pset = PrimeSet::new();
let (ix, n) = pset.find(1_000);
println!("The first prime after 1000 is the {}th prime: {}", ix, n);

assert_eq!(pset.find(n), (ix, n));
```

*/

#[warn(non_camel_case_types)]
#[warn(non_snake_case)]
#[warn(unused_qualifications)]
#[warn(non_upper_case_globals)]
#[warn(missing_docs)]

#[cfg(test)]
extern crate test;

use std::ops::Index;
use std::slice;
use std::iter;
use std::num::{Float,cast};
use std::cmp::Ordering::{Equal,Less,Greater};

#[cfg(test)]
use test::Bencher;

fn sqrt_floor<T: std::num::NumCast>(n : T) -> T {
    cast::<f64, T>(
        (cast::<T, f64>(n).unwrap()).sqrt().floor()
    ).unwrap()
}

fn sqrt_ceil<T: std::num::NumCast>(n : T) -> T {
    cast::<f64, T>(
        (cast::<T, f64>(n).unwrap()).sqrt().ceil()
    ).unwrap()
}

/** A prime generator, using the Sieve of Eratosthenes.

Create with `let mut pset = PrimeSet::new()`, and then use `pset.iter()` to iterate over all primes.
**/
pub struct PrimeSet {
    lst : Vec<u64>
}

/// An iterator over generated primes. Created by PrimeSet::iter or
/// PrimeSet::generator
pub struct PrimeSetIter<'a> {
    p : &'a mut PrimeSet,
    n : usize,
    expand : bool
}

impl PrimeSet {
    /// A new prime generator, primed with 2 and 3
    pub fn new() -> PrimeSet {
        PrimeSet{lst:vec!(2,3)}
    }

    /// Finds one more prime, and adds it to the list
    pub fn expand(&mut self) {
        let mut l : u64 = self.lst[self.lst.len()-1] + 2;
        let mut sql = sqrt_floor(l);
        let mut remainder = 0;
        loop {
            for &n in self.lst.iter() {
                remainder = l % n;
                if remainder == 0 || n > sql {
                    break;
                }
            };

            if remainder != 0 {
                self.lst.push(l);
                break;
            };

            l += 2;
            sql = sqrt_floor(l);
        }
    }

    /// Number of primes found so far
    pub fn len(&self) -> usize {
        self.lst.len()
    }

    /// Return all primes found so far as a slice
    pub fn list<'a>(&'a self) -> &'a [u64] {
        &self.lst[]
    }

    /// Iterator over all primes not yet found
    pub fn generator<'a>(&'a mut self) -> PrimeSetIter<'a> {
        let myn = self.len();
        PrimeSetIter{p:self, n:myn, expand:true}
    }

    /// Iterator over all primes, starting with 2. If you don't care about the "state" of the
    /// PrimeSet, this is what you want!
    pub fn iter<'a>(&'a mut self) -> PrimeSetIter<'a> {
        PrimeSetIter{p:self, n:0, expand:true}
    }

    //~ pub fn iter_once(&'self mut self) -> PrimeSetIter<'self> {
        //~ PrimeSetIter{p:self, n:0, expand:false}
    //~ }

    /// Iterator over just the primes found so far
    pub fn iter_vec<'a>(&'a self) -> slice::Iter<'a, u64> {
        self.lst.iter()
    }

    /// Find the next largest prime from a number
    /// Returns (idx, prime)
    /// Note that if n is prime, then the output will be (idx, n)
    pub fn find(&mut self, n: u64) -> (usize, u64) {
        while n > *(self.lst.last().unwrap_or(&0)){
            self.expand();
        }
        self.find_vec(n).unwrap()
    }

    /// Check if a number is prime
    /// Note that this only requires primes up to n.sqrt() to be generated, and will generate
    /// them as necessary on its own.
    pub fn is_prime(&mut self, n: u64) -> bool {
        if n <= 1 {return false;}
        if n == 2 {return true;} // otherwise we get 2 % 2 == 0!
        for m in self.iter() {
            if n % m == 0 {return false;};
            if m*m > n {return true;};
        }
        panic!("This iterator should not be empty.");
    }

    /// Find the next largest prime from a number, if it is within the already-found list
    /// Returns (idx, prime)
    /// Note that if n is prime, then the output will be (idx, n)
    pub fn find_vec(&self, n: u64) -> Option<(usize, u64)> {
        if n > *(self.lst.last().unwrap_or(&0)){ return None;}

        let mut base : usize = 0;
        let mut lim : usize = self.len();

        // Binary search algorithm
        while lim != 0 {
            let ix = base + (lim >> 1);
            match self.lst[ix].cmp(&n) {
                Equal => return Some((ix, self.lst[ix])),
                Less => {
                    base = ix + 1;
                    lim -= 1;
                }
                Greater => ()
            }
            lim >>= 1;
        }
        return Some((base, self.lst[base]));
    }

    /// Get the nth prime, even if we haven't yet found it
    pub fn get(&mut self, index : &usize) -> &u64 {
		for _ in (0..(*index as isize) + 1 - (self.lst.len() as isize)){
			self.expand();
		}
        self.lst.index(index)
	}

	/// Get the prime factors of a number, starting from 2, including repeats
	pub fn prime_factors(&mut self, n: u64) -> Vec<u64> {
		if n == 1 {return Vec::new();}
		let mut curn = n;
		let mut m = sqrt_ceil(curn);
		let mut lst: Vec<u64> = Vec::new();
		for p in self.iter() {
			while curn % p == 0 {
				lst.push(p);
				curn /= p;
				if curn == 1 {return lst;}
				m = sqrt_ceil(curn);
			}

			if p > m {
				lst.push(p);
				return lst;
			}
		}
		panic!("This should be unreachable.");
	}
}

impl Index<usize> for PrimeSet {
    type Output = u64;
    fn index(&self, index: &usize) -> &u64 {
        self.lst.index(index)
    }
}

impl<'a> Iterator for PrimeSetIter<'a> {
    type Item = u64;
    fn next(&mut self) -> Option<u64> {
        while self.n >= self.p.len(){
            match self.expand {
                true => self.p.expand(),
                false => return None
            }
        }
        self.n += 1;

        let m = self.p.lst[self.n-1];

        Some(m)
    }
}

/// Find the first factor (other than 1) of a number
fn firstfac(x: u64) -> u64 {
    let m = sqrt_ceil(x);
    if x % 2 == 0 { return 2; };
    for n in iter::range_step(3, m + 1, 2) {
        if x % n == 0 { return n; };
    }
    return x;
}

/// Find all prime factors of a number
/// Does not use a PrimeSet, but simply counts upwards
pub fn factors(x: u64) -> Vec<u64> {
    if x <= 1 {return vec!()};
    let mut lst: Vec<u64> = Vec::new();
    let mut curn = x;
    loop  {
        let m = firstfac(curn);
        lst.push(m);
        if m == curn { break  } else { curn /= m };
    }
    return lst
}

/// Find all unique prime factors of a number
pub fn factors_uniq(x: u64) -> Vec<u64> {
    if x <= 1 {return vec!()};
    let mut lst: Vec<u64> = Vec::new();
    let mut curn = x;
    loop  {
        let m = firstfac(curn);
        lst.push(m);
        if curn == m { break ; }
        while curn % m == 0 { curn /= m; }
        if curn == 1 { break ; }
    }
    return lst
}

/// Test whether a number is prime. Checks every odd number up to sqrt(n).
pub fn is_prime(n : u64) -> bool {
    if n <= 1 {return false;}
    firstfac(n) == n
}

#[test]
fn test_iter(){
    let mut pset = PrimeSet::new();
    let first_few = [2u64,3,5,7,11,13,17,19,23];
    for (m, &n) in pset.iter().zip(first_few.iter()) {
        assert_eq!(m, n);
    }
}

#[test]
fn test_find(){
    let mut pset = PrimeSet::new();

    // pset is empty, so it needs to generate the primes
    assert_eq!(pset.find_vec(1000), None);

    let (ix_exp, n_exp) = (168, 1009);

    assert_eq!(pset.find(1000), (ix_exp, n_exp));
    assert_eq!(pset.find(n_exp), (ix_exp, n_exp));

    // We shouldn't have gone beyond 1009
    {
        let plst = pset.list();
        let plen = plst.len();
        assert_eq!(plen, ix_exp+1);

        assert_eq!(plst[plen-1], n_exp);
    }

    assert_eq!(pset.find_vec(n_exp), Some((ix_exp, n_exp)));
}

#[test]
fn test_primes(){
    let mut pset = PrimeSet::new();

    // note: some are repeated, because the pset list grows as it goes

    assert!(!pset.is_prime(1));
    assert!(!is_prime(1));
    assert!(pset.is_prime(2));
    assert!(is_prime(2));
    assert!(pset.is_prime(13));
    assert!(is_prime(13));
    assert!(!pset.is_prime(45));
    assert!(!is_prime(45));
    assert!(!pset.is_prime(13*13));
    assert!(!is_prime(13*13));
    assert!(pset.is_prime(13));
    assert!(pset.is_prime(7));
    assert!(is_prime(7));
    assert!(!pset.is_prime(9));
    assert!(!is_prime(9));
    assert!(pset.is_prime(5));
    assert!(is_prime(5));
}

#[test]
fn test_factors(){
	let mut pset = PrimeSet::new();

	let ns = [  (1, vec!()),
                (2, vec!(2)),
                (3, vec!(3)),
                (4, vec!(2,2)),
                (5, vec!(5)),
                (6, vec!(2,3)),
	            (9, vec!(3,3)),
	            (12, vec!(2,2,3)),
	            (121, vec!(11,11)),
	            (144, vec!(2,2,2,2,3,3)),
	            (10_000_000, vec!(2,2,2,2,2,2,2,5,5,5,5,5,5,5)),
                (100, vec!(2,2,5,5)),
                (121, vec!(11, 11)),
                ];

    // Test unique factors
    for &(n, ref v) in ns.iter(){
        assert_eq!(pset.prime_factors(n), *v);
        assert_eq!(factors(n), *v);

        let unique_factors = factors_uniq(n);

        // Get unique factors from the lists we made above
        let mut unique_factors_exp : Vec<u64> = v.iter().map(|&x| {x}).collect();
        unique_factors_exp.dedup();

        assert_eq!(unique_factors, unique_factors_exp);
    }

	pset = PrimeSet::new();
	assert_eq!(pset.prime_factors(12), vec!(2,2,3));

}

#[bench]
fn bench_primes(b : &mut Bencher){
	b.iter(|| {
		let mut pset = PrimeSet::new();
		 let (_, _) = pset.find(1_000_000);
		 //~ let (idx, n) = pset.find(1_000_000);
		 //~ println!("Prime {}: {}", idx, n);
		 })
}
<commit_msg>Updated to use features<commit_after>/*!

A basic library for finding primes, providing a basic Iterator over all primes.
It is not as fast as `slow_primes`, but it is meant to be easy to use!

The simplest usage is simply to create an `Iterator`:

```
use primes::PrimeSet;

let mut pset = PrimeSet::new();

for (ix, n) in pset.iter().enumerate().take(10) {
    println!("Prime {}: {}", ix, n);
}
```

This library provides methods for generating primes, testing whether a number
is prime, and factorizing numbers. Most methods generate primes lazily, so
only enough primes will be generated for the given test, and primes are cached
for later use.

To use, see `PrimeSet`, a class which handles the Sieve and has multiple
methods for iterating over primes.

This also provides a few functions unconnected to `PrimeSet`, which will be
faster for the first case, but slower in the long term as they do not use any
caching of primes.

[*Source*](https://github.com/wackywendell/primes)

# Example: Find the millionth prime

```
use primes::PrimeSet;

let mut pset = PrimeSet::new();
let (ix, n) = pset.find(1_000_000);

println!("Prime {}: {}", ix, n);
```

# Example: Find the first ten primes *after* the thousandth prime
```
use primes::PrimeSet;

let mut pset = PrimeSet::new();
for (ix, n) in pset.iter().enumerate().skip(1_000).take(10) {
    println!("Prime {}: {}", ix, n);
}
```

# Example: Find the first prime greater than 1000
```
use primes::PrimeSet;

let mut pset = PrimeSet::new();
let (ix, n) = pset.find(1_000);
println!("The first prime after 1000 is the {}th prime: {}", ix, n);

assert_eq!(pset.find(n), (ix, n));
```

*/
#![feature(core)]
#![feature(test)]

#[warn(non_camel_case_types)]
#[warn(non_snake_case)]
#[warn(unused_qualifications)]
#[warn(non_upper_case_globals)]
#[warn(missing_docs)]

extern crate test;

use std::ops::Index;
use std::slice;
use std::iter;
use std::num::{Float,cast};
use std::cmp::Ordering::{Equal,Less,Greater};

#[cfg(test)]
use test::Bencher;

fn sqrt_floor<T: std::num::NumCast>(n : T) -> T {
    cast::<f64, T>(
        (cast::<T, f64>(n).unwrap()).sqrt().floor()
    ).unwrap()
}

fn sqrt_ceil<T: std::num::NumCast>(n : T) -> T {
    cast::<f64, T>(
        (cast::<T, f64>(n).unwrap()).sqrt().ceil()
    ).unwrap()
}

/** A prime generator, using the Sieve of Eratosthenes.

Create with `let mut pset = PrimeSet::new()`, and then use `pset.iter()` to iterate over all primes.
**/
pub struct PrimeSet {
    lst : Vec<u64>
}

/// An iterator over generated primes. Created by PrimeSet::iter or
/// PrimeSet::generator
pub struct PrimeSetIter<'a> {
    p : &'a mut PrimeSet,
    n : usize,
    expand : bool
}

impl PrimeSet {
    /// A new prime generator, primed with 2 and 3
    pub fn new() -> PrimeSet {
        PrimeSet{lst:vec!(2,3)}
    }

    /// Finds one more prime, and adds it to the list
    pub fn expand(&mut self) {
        let mut l : u64 = self.lst[self.lst.len()-1] + 2;
        let mut sql = sqrt_floor(l);
        let mut remainder = 0;
        loop {
            for &n in self.lst.iter() {
                remainder = l % n;
                if remainder == 0 || n > sql {
                    break;
                }
            };

            if remainder != 0 {
                self.lst.push(l);
                break;
            };

            l += 2;
            sql = sqrt_floor(l);
        }
    }

    /// Number of primes found so far
    pub fn len(&self) -> usize {
        self.lst.len()
    }

    /// Return all primes found so far as a slice
    pub fn list<'a>(&'a self) -> &'a [u64] {
        &self.lst[..]
    }

    /// Iterator over all primes not yet found
    pub fn generator<'a>(&'a mut self) -> PrimeSetIter<'a> {
        let myn = self.len();
        PrimeSetIter{p:self, n:myn, expand:true}
    }

    /// Iterator over all primes, starting with 2. If you don't care about the "state" of the
    /// PrimeSet, this is what you want!
    pub fn iter<'a>(&'a mut self) -> PrimeSetIter<'a> {
        PrimeSetIter{p:self, n:0, expand:true}
    }

    //~ pub fn iter_once(&'self mut self) -> PrimeSetIter<'self> {
        //~ PrimeSetIter{p:self, n:0, expand:false}
    //~ }

    /// Iterator over just the primes found so far
    pub fn iter_vec<'a>(&'a self) -> slice::Iter<'a, u64> {
        self.lst.iter()
    }

    /// Find the next largest prime from a number
    /// Returns (idx, prime)
    /// Note that if n is prime, then the output will be (idx, n)
    pub fn find(&mut self, n: u64) -> (usize, u64) {
        while n > *(self.lst.last().unwrap_or(&0)){
            self.expand();
        }
        self.find_vec(n).unwrap()
    }

    /// Check if a number is prime
    /// Note that this only requires primes up to n.sqrt() to be generated, and will generate
    /// them as necessary on its own.
    pub fn is_prime(&mut self, n: u64) -> bool {
        if n <= 1 {return false;}
        if n == 2 {return true;} // otherwise we get 2 % 2 == 0!
        for m in self.iter() {
            if n % m == 0 {return false;};
            if m*m > n {return true;};
        }
        panic!("This iterator should not be empty.");
    }

    /// Find the next largest prime from a number, if it is within the already-found list
    /// Returns (idx, prime)
    /// Note that if n is prime, then the output will be (idx, n)
    pub fn find_vec(&self, n: u64) -> Option<(usize, u64)> {
        if n > *(self.lst.last().unwrap_or(&0)){ return None;}

        let mut base : usize = 0;
        let mut lim : usize = self.len();

        // Binary search algorithm
        while lim != 0 {
            let ix = base + (lim >> 1);
            match self.lst[ix].cmp(&n) {
                Equal => return Some((ix, self.lst[ix])),
                Less => {
                    base = ix + 1;
                    lim -= 1;
                }
                Greater => ()
            }
            lim >>= 1;
        }
        return Some((base, self.lst[base]));
    }

    /// Get the nth prime, even if we haven't yet found it
    pub fn get(&mut self, index : &usize) -> &u64 {
		for _ in (0..(*index as isize) + 1 - (self.lst.len() as isize)){
			self.expand();
		}
        self.lst.index(index)
	}

	/// Get the prime factors of a number, starting from 2, including repeats
	pub fn prime_factors(&mut self, n: u64) -> Vec<u64> {
		if n == 1 {return Vec::new();}
		let mut curn = n;
		let mut m = sqrt_ceil(curn);
		let mut lst: Vec<u64> = Vec::new();
		for p in self.iter() {
			while curn % p == 0 {
				lst.push(p);
				curn /= p;
				if curn == 1 {return lst;}
				m = sqrt_ceil(curn);
			}

			if p > m {
				lst.push(p);
				return lst;
			}
		}
		panic!("This should be unreachable.");
	}
}

impl Index<usize> for PrimeSet {
    type Output = u64;
    fn index(&self, index: &usize) -> &u64 {
        self.lst.index(index)
    }
}

impl<'a> Iterator for PrimeSetIter<'a> {
    type Item = u64;
    fn next(&mut self) -> Option<u64> {
        while self.n >= self.p.len(){
            match self.expand {
                true => self.p.expand(),
                false => return None
            }
        }
        self.n += 1;

        let m = self.p.lst[self.n-1];

        Some(m)
    }
}

/// Find the first factor (other than 1) of a number
fn firstfac(x: u64) -> u64 {
    let m = sqrt_ceil(x);
    if x % 2 == 0 { return 2; };
    for n in iter::range_step(3, m + 1, 2) {
        if x % n == 0 { return n; };
    }
    return x;
}

/// Find all prime factors of a number
/// Does not use a PrimeSet, but simply counts upwards
pub fn factors(x: u64) -> Vec<u64> {
    if x <= 1 {return vec!()};
    let mut lst: Vec<u64> = Vec::new();
    let mut curn = x;
    loop  {
        let m = firstfac(curn);
        lst.push(m);
        if m == curn { break  } else { curn /= m };
    }
    return lst
}

/// Find all unique prime factors of a number
pub fn factors_uniq(x: u64) -> Vec<u64> {
    if x <= 1 {return vec!()};
    let mut lst: Vec<u64> = Vec::new();
    let mut curn = x;
    loop  {
        let m = firstfac(curn);
        lst.push(m);
        if curn == m { break ; }
        while curn % m == 0 { curn /= m; }
        if curn == 1 { break ; }
    }
    return lst
}

/// Test whether a number is prime. Checks every odd number up to sqrt(n).
pub fn is_prime(n : u64) -> bool {
    if n <= 1 {return false;}
    firstfac(n) == n
}

#[test]
fn test_iter(){
    let mut pset = PrimeSet::new();
    let first_few = [2u64,3,5,7,11,13,17,19,23];
    for (m, &n) in pset.iter().zip(first_few.iter()) {
        assert_eq!(m, n);
    }
}

#[test]
fn test_find(){
    let mut pset = PrimeSet::new();

    // pset is empty, so it needs to generate the primes
    assert_eq!(pset.find_vec(1000), None);

    let (ix_exp, n_exp) = (168, 1009);

    assert_eq!(pset.find(1000), (ix_exp, n_exp));
    assert_eq!(pset.find(n_exp), (ix_exp, n_exp));

    // We shouldn't have gone beyond 1009
    {
        let plst = pset.list();
        let plen = plst.len();
        assert_eq!(plen, ix_exp+1);

        assert_eq!(plst[plen-1], n_exp);
    }

    assert_eq!(pset.find_vec(n_exp), Some((ix_exp, n_exp)));
}

#[test]
fn test_primes(){
    let mut pset = PrimeSet::new();

    // note: some are repeated, because the pset list grows as it goes

    assert!(!pset.is_prime(1));
    assert!(!is_prime(1));
    assert!(pset.is_prime(2));
    assert!(is_prime(2));
    assert!(pset.is_prime(13));
    assert!(is_prime(13));
    assert!(!pset.is_prime(45));
    assert!(!is_prime(45));
    assert!(!pset.is_prime(13*13));
    assert!(!is_prime(13*13));
    assert!(pset.is_prime(13));
    assert!(pset.is_prime(7));
    assert!(is_prime(7));
    assert!(!pset.is_prime(9));
    assert!(!is_prime(9));
    assert!(pset.is_prime(5));
    assert!(is_prime(5));
}

#[test]
fn test_factors(){
	let mut pset = PrimeSet::new();

	let ns = [  (1, vec!()),
                (2, vec!(2)),
                (3, vec!(3)),
                (4, vec!(2,2)),
                (5, vec!(5)),
                (6, vec!(2,3)),
	            (9, vec!(3,3)),
	            (12, vec!(2,2,3)),
	            (121, vec!(11,11)),
	            (144, vec!(2,2,2,2,3,3)),
	            (10_000_000, vec!(2,2,2,2,2,2,2,5,5,5,5,5,5,5)),
                (100, vec!(2,2,5,5)),
                (121, vec!(11, 11)),
                ];

    // Test unique factors
    for &(n, ref v) in ns.iter(){
        assert_eq!(pset.prime_factors(n), *v);
        assert_eq!(factors(n), *v);

        let unique_factors = factors_uniq(n);

        // Get unique factors from the lists we made above
        let mut unique_factors_exp : Vec<u64> = v.iter().map(|&x| {x}).collect();
        unique_factors_exp.dedup();

        assert_eq!(unique_factors, unique_factors_exp);
    }

	pset = PrimeSet::new();
	assert_eq!(pset.prime_factors(12), vec!(2,2,3));

}

#[bench]
fn bench_primes(b : &mut Bencher){
	b.iter(|| {
		let mut pset = PrimeSet::new();
		 let (_, _) = pset.find(1_000_000);
		 //~ let (idx, n) = pset.find(1_000_000);
		 //~ println!("Prime {}: {}", idx, n);
		 })
}
<|endoftext|>