<commit_before>use fern;
use failure::{Error};
use better_panic;
extern crate log;
extern crate clap;
extern crate chrono;

fn run(sig_path: &str) -> Result<(), Error> {
    let buf = std::fs::read(sig_path)?;

    for sig in flirt::sig::parse(&buf)?.iter() {
        println!("{:}", sig);
    }

    Ok(())
}

fn main() {
    better_panic::install();

    // while the macro form of clap is more readable,
    // it doesn't seem to allow us to use dynamically-generated values,
    // such as the defaults pulled from env vars, etc.
    let matches = clap::App::new("sig2pat")
        .author("Willi Ballenthin <willi.ballenthin@gmail.com>")
        .about("translate a FLIRT .sig file into a .pat file")
        .arg(clap::Arg::with_name("verbose")
            .short("v")
            .long("verbose")
            .multiple(true)
            .help("log verbose messages")
        )
        .arg(clap::Arg::with_name("sig")
            .required(true)
            .index(1)
            .help("path to .sig file")
        ).get_matches();

    let log_level = match matches.occurrences_of("verbose") {
        0 => log::LevelFilter::Info,
        1 => log::LevelFilter::Debug,
        2 => log::LevelFilter::Trace,
        _ => log::LevelFilter::Trace,
    };

    fern::Dispatch::new()
        .format(move |out, message, record| {
            out.finish(format_args!(
                "{} [{:5}] {} {}",
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                record.level(),
                if log_level == log::LevelFilter::Trace {record.target()} else {""},
                message
            ))
        })
        .level(log_level)
        .chain(std::io::stderr())
        .apply()
        .expect("failed to configure logging");

    if let Err(e) = run(matches.value_of("sig").unwrap()) {
        println!("error: {:}", e);
    }
}
<commit_msg>flirt: add sig decompression utility<commit_after>use fern;
use failure::{Error};
use better_panic;
extern crate log;
extern crate clap;
extern crate chrono;

fn run(sig_path: &str, output_path: &str) -> Result<(), Error> {
    let buf = std::fs::read(sig_path)?;
    let buf = flirt::sig::unpack_sig(&buf)?;

    std::fs::write(output_path, &buf)?;

    Ok(())
}

fn main() {
    better_panic::install();

    // while the macro form of clap is more readable,
    // it doesn't seem to allow us to use dynamically-generated values,
    // such as the defaults pulled from env vars, etc.
    let matches = clap::App::new("sig2pat")
        .author("Willi Ballenthin <willi.ballenthin@gmail.com>")
        .about("translate a FLIRT .sig file into a .pat file")
        .arg(clap::Arg::with_name("verbose")
            .short("v")
            .long("verbose")
            .multiple(true)
            .help("log verbose messages")
        )
        .arg(clap::Arg::with_name("sig")
            .required(true)
            .index(1)
            .help("path to .sig file")
        )
        .arg(clap::Arg::with_name("output")
            .required(true)
            .index(2)
            .help("path to output file")
        )
        .get_matches();

    let log_level = match matches.occurrences_of("verbose") {
        0 => log::LevelFilter::Info,
        1 => log::LevelFilter::Debug,
        2 => log::LevelFilter::Trace,
        _ => log::LevelFilter::Trace,
    };

    fern::Dispatch::new()
        .format(move |out, message, record| {
            out.finish(format_args!(
                "{} [{:5}] {} {}",
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                record.level(),
                if log_level == log::LevelFilter::Trace {record.target()} else {""},
                message
            ))
        })
        .level(log_level)
        .chain(std::io::stderr())
        .apply()
        .expect("failed to configure logging");

    if let Err(e) = run(
        matches.value_of("sig").unwrap(),
        matches.value_of("output").unwrap()
    ) {
        println!("error: {:}", e);
    }
}
<|endoftext|>


<commit_before>use ::xen::hypercalls::*;
use ::xen::hypercalls::grant_table_op::PFN;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct Args {
    pub dom             : DomID,
    pub nr_frames       : u32,
    /// Output
    pub status          : i16,      // See enum grant_status
    /// Output
    pub frame_list      : *mut PFN
}<commit_msg>fix import<commit_after>use ::xen::hypercalls::DomID;
use ::xen::hypercalls::grant_table_op::PFN;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct Args {
    pub dom             : DomID,
    pub nr_frames       : u32,
    /// Output
    pub status          : i16,      // See enum grant_status
    /// Output
    pub frame_list      : *mut PFN
}<|endoftext|>


<commit_before>use std::convert::From;
use std::error::Error as StdError;
use std::fmt::{self, Display};
use std::ffi::NulError;

#[derive(Debug)]
#[cfg_attr(feature = "clippy", allow(enum_variant_names))]
/// The generic "things can fail in a myriad of ways" enum. This type is not
/// intended to be exhaustively matched, and new variants may be added in the
/// future without a major version bump.
pub enum Error {
    InvalidCString(NulError),
    DatabaseError(
        DatabaseErrorKind,
        Box<DatabaseErrorInformation + Send + Sync>,
    ),
    NotFound,
    QueryBuilderError(Box<StdError + Send + Sync>),
    DeserializationError(Box<StdError + Send + Sync>),
    SerializationError(Box<StdError + Send + Sync>),
    /// You can return this variant inside of a transaction when you want to
    /// roll it back, but have no actual error to return. Diesel will never
    /// return this variant unless you gave it to us, and it can be safely
    /// ignored in error handling.
    RollbackTransaction,
    #[doc(hidden)] __Nonexhaustive,
}

#[derive(Debug, Clone, Copy)]
/// The kind of database error that occurred. This is not meant to exhaustively
/// cover all possible errors, but is used to identify errors which are commonly
/// recovered from programatically. This enum is not intended to be exhaustively
/// matched, and new variants may be added in the future without a major version
/// bump.
pub enum DatabaseErrorKind {
    UniqueViolation,
    ForeignKeyViolation,
    UnableToSendCommand,
    #[doc(hidden)] __Unknown, // Match against _ instead, more variants may be added in the future
}

pub trait DatabaseErrorInformation {
    fn message(&self) -> &str;
    fn details(&self) -> Option<&str>;
    fn hint(&self) -> Option<&str>;
    fn table_name(&self) -> Option<&str>;
    fn column_name(&self) -> Option<&str>;
    fn constraint_name(&self) -> Option<&str>;
}

impl fmt::Debug for DatabaseErrorInformation + Send + Sync {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.message(), f)
    }
}

impl DatabaseErrorInformation for String {
    fn message(&self) -> &str {
        self
    }

    fn details(&self) -> Option<&str> {
        None
    }
    fn hint(&self) -> Option<&str> {
        None
    }
    fn table_name(&self) -> Option<&str> {
        None
    }
    fn column_name(&self) -> Option<&str> {
        None
    }
    fn constraint_name(&self) -> Option<&str> {
        None
    }
}

#[derive(Debug)]
pub enum ConnectionError {
    InvalidCString(NulError),
    BadConnection(String),
    InvalidConnectionUrl(String),
    /// Diesel may try to automatically set session specific configuration
    /// values, such as UTF8 encoding, or enabling the `||` operator on MySQL.
    /// This variant is returned if an error occurred executing the query to set
    /// those options. Diesel will never affect global configuration.
    CouldntSetupConfiguration(Error),
    #[doc(hidden)] __Nonexhaustive, // Match against _ instead, more variants may be added in the future
}

/// A specialized result type for queries.
///
/// This type is exported by `diesel::prelude`, and is generally used by any
/// code which is interacting with Diesel. This type exists to avoid writing out
/// `diesel::result::Error`, and is otherwise a direct mapping to `Result`.
pub type QueryResult<T> = Result<T, Error>;

/// A specialized result type for establishing connections.
///
/// This type exists to avoid writing out `diesel::result::ConnectionError`, and
/// is otherwise a direct mapping to `Result`.
pub type ConnectionResult<T> = Result<T, ConnectionError>;

/// See the [method documentation](#tymethod.optional).
pub trait OptionalExtension<T> {
    /// Converts a `QueryResult<T>` into a `QueryResult<Option<T>>`.
    ///
    /// By default, Diesel treats 0 rows being returned from a query that is expected to return 1
    /// row as an error (e.g. the return value of [`get_result`] or [`first`]). This method will
    /// handle that error, and give you back an `Option<T>` instead.
    ///
    /// [`get_result`]: ../prelude/trait.LoadDsl.html#method.get_result
    /// [`first`]: ../prelude/trait.FirstDsl.html#method.first
    ///
    /// # Example
    ///
    /// ```rust
    /// use diesel::result::{QueryResult, Error};
    /// use diesel::OptionalExtension;
    ///
    /// let result: QueryResult<i32> = Ok(1);
    /// assert_eq!(Ok(Some(1)), result.optional());
    ///
    /// let result: QueryResult<i32> = Err(Error::NotFound);
    /// assert_eq!(Ok(None), result.optional());
    /// ```
    fn optional(self) -> Result<Option<T>, Error>;
}

impl<T> OptionalExtension<T> for QueryResult<T> {
    fn optional(self) -> Result<Option<T>, Error> {
        match self {
            Ok(value) => Ok(Some(value)),
            Err(Error::NotFound) => Ok(None),
            Err(e) => Err(e),
        }
    }
}

impl From<NulError> for ConnectionError {
    fn from(e: NulError) -> Self {
        ConnectionError::InvalidCString(e)
    }
}

impl From<NulError> for Error {
    fn from(e: NulError) -> Self {
        Error::InvalidCString(e)
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::InvalidCString(ref nul_err) => nul_err.fmt(f),
            Error::DatabaseError(_, ref e) => write!(f, "{}", e.message()),
            Error::NotFound => f.write_str("NotFound"),
            Error::QueryBuilderError(ref e) => e.fmt(f),
            Error::DeserializationError(ref e) => e.fmt(f),
            Error::SerializationError(ref e) => e.fmt(f),
            Error::RollbackTransaction => write!(f, "{}", self.description()),
            Error::__Nonexhaustive => unreachable!(),
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidCString(ref nul_err) => nul_err.description(),
            Error::DatabaseError(_, ref e) => e.message(),
            Error::NotFound => "Record not found",
            Error::QueryBuilderError(ref e) => e.description(),
            Error::DeserializationError(ref e) => e.description(),
            Error::SerializationError(ref e) => e.description(),
            Error::RollbackTransaction => "The current transaction was aborted",
            Error::__Nonexhaustive => unreachable!(),
        }
    }
}

impl Display for ConnectionError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ConnectionError::InvalidCString(ref nul_err) => nul_err.fmt(f),
            ConnectionError::BadConnection(ref s) => write!(f, "{}", s),
            ConnectionError::InvalidConnectionUrl(ref s) => write!(f, "{}", s),
            ConnectionError::CouldntSetupConfiguration(ref e) => e.fmt(f),
            ConnectionError::__Nonexhaustive => unreachable!(),
        }
    }
}

impl StdError for ConnectionError {
    fn description(&self) -> &str {
        match *self {
            ConnectionError::InvalidCString(ref nul_err) => nul_err.description(),
            ConnectionError::BadConnection(ref s) => s,
            ConnectionError::InvalidConnectionUrl(ref s) => s,
            ConnectionError::CouldntSetupConfiguration(ref e) => e.description(),
            ConnectionError::__Nonexhaustive => unreachable!(),
        }
    }
}

impl PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        match (self, other) {
            (&Error::InvalidCString(ref a), &Error::InvalidCString(ref b)) => a == b,
            (&Error::DatabaseError(_, ref a), &Error::DatabaseError(_, ref b)) => {
                a.message() == b.message()
            }
            (&Error::NotFound, &Error::NotFound) => true,
            _ => false,
        }
    }
}

#[cfg(test)]
#[allow(warnings)]
fn error_impls_send() {
    let err: Error = unimplemented!();
    let x: &Send = &err;
}

pub(crate) fn first_or_not_found<T>(records: QueryResult<Vec<T>>) -> QueryResult<T> {
    records?.into_iter().next().ok_or(Error::NotFound)
}
<commit_msg>Document `diesel::result::Error` [ci skip]<commit_after>use std::convert::From;
use std::error::Error as StdError;
use std::fmt::{self, Display};
use std::ffi::NulError;

#[derive(Debug)]
#[cfg_attr(feature = "clippy", allow(enum_variant_names))]
/// The generic "things can fail in a myriad of ways" enum.
///
/// This type is not intended to be exhaustively matched, and new variants may
/// be added in the future without a major version bump.
pub enum Error {
    /// The query contained a nul byte.
    InvalidCString(NulError),
    /// The database returned an error.
    ///
    /// While Diesel prevents almost all sources of runtime errors at compile
    /// time, it does not attempt to prevent 100% of them. Typically this error
    /// will occur from insert or update statements due to a constraint
    /// violation.
    DatabaseError(
        DatabaseErrorKind,
        Box<DatabaseErrorInformation + Send + Sync>,
    ),
    /// No rows were returned by a query expected to return at least one row.
    ///
    /// This variant is only returned by [`get_result`] and [`first`]. [`load`]
    /// does not treat 0 rows as an error. If you would like to allow either 0
    /// or 1 rows, call [`optional`] on the result.
    ///
    /// [`get_result`]: ../prelude/trait.LoadDsl.html#method.get_result
    /// [`first`]: ../prelude/trait.FirstDsl.html#method.first
    /// [`load`]: ../prelude/trait.LoadDsl.html#method.load
    /// [`optional`]: trait.OptionalExtension.html#tymethod.optional
    NotFound,
    /// The query could not be constructed
    ///
    /// An example of when this error could occur is if you are attempting to
    /// construct an update statement with no changes (e.g. all fields on the
    /// struct are `None`).
    QueryBuilderError(Box<StdError + Send + Sync>),
    /// An error occurred deserializing the data being sent to the database.
    ///
    /// Typically this error means that the stated type of the query is
    /// incorrect. An example of when this error might occur in normal usage is
    /// attempting to deserialize an infinite date into chrono.
    DeserializationError(Box<StdError + Send + Sync>),
    /// An error occurred serializing the data being sent to the database.
    ///
    /// An example of when this error would be returned is if you attempted to
    /// serialize a `chrono::NaiveDate` earlier than the earliest date supported
    /// by PostgreSQL.
    SerializationError(Box<StdError + Send + Sync>),
    /// Roll back the current transaction.
    ///
    /// You can return this variant inside of a transaction when you want to
    /// roll it back, but have no actual error to return. Diesel will never
    /// return this variant unless you gave it to us, and it can be safely
    /// ignored in error handling.
    RollbackTransaction,
    #[doc(hidden)] __Nonexhaustive,
}

#[derive(Debug, Clone, Copy)]
/// The kind of database error that occurred. This is not meant to exhaustively
/// cover all possible errors, but is used to identify errors which are commonly
/// recovered from programatically. This enum is not intended to be exhaustively
/// matched, and new variants may be added in the future without a major version
/// bump.
pub enum DatabaseErrorKind {
    UniqueViolation,
    ForeignKeyViolation,
    UnableToSendCommand,
    #[doc(hidden)] __Unknown, // Match against _ instead, more variants may be added in the future
}

pub trait DatabaseErrorInformation {
    fn message(&self) -> &str;
    fn details(&self) -> Option<&str>;
    fn hint(&self) -> Option<&str>;
    fn table_name(&self) -> Option<&str>;
    fn column_name(&self) -> Option<&str>;
    fn constraint_name(&self) -> Option<&str>;
}

impl fmt::Debug for DatabaseErrorInformation + Send + Sync {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.message(), f)
    }
}

impl DatabaseErrorInformation for String {
    fn message(&self) -> &str {
        self
    }

    fn details(&self) -> Option<&str> {
        None
    }
    fn hint(&self) -> Option<&str> {
        None
    }
    fn table_name(&self) -> Option<&str> {
        None
    }
    fn column_name(&self) -> Option<&str> {
        None
    }
    fn constraint_name(&self) -> Option<&str> {
        None
    }
}

#[derive(Debug)]
pub enum ConnectionError {
    InvalidCString(NulError),
    BadConnection(String),
    InvalidConnectionUrl(String),
    /// Diesel may try to automatically set session specific configuration
    /// values, such as UTF8 encoding, or enabling the `||` operator on MySQL.
    /// This variant is returned if an error occurred executing the query to set
    /// those options. Diesel will never affect global configuration.
    CouldntSetupConfiguration(Error),
    #[doc(hidden)] __Nonexhaustive, // Match against _ instead, more variants may be added in the future
}

/// A specialized result type for queries.
///
/// This type is exported by `diesel::prelude`, and is generally used by any
/// code which is interacting with Diesel. This type exists to avoid writing out
/// `diesel::result::Error`, and is otherwise a direct mapping to `Result`.
pub type QueryResult<T> = Result<T, Error>;

/// A specialized result type for establishing connections.
///
/// This type exists to avoid writing out `diesel::result::ConnectionError`, and
/// is otherwise a direct mapping to `Result`.
pub type ConnectionResult<T> = Result<T, ConnectionError>;

/// See the [method documentation](#tymethod.optional).
pub trait OptionalExtension<T> {
    /// Converts a `QueryResult<T>` into a `QueryResult<Option<T>>`.
    ///
    /// By default, Diesel treats 0 rows being returned from a query that is expected to return 1
    /// row as an error (e.g. the return value of [`get_result`] or [`first`]). This method will
    /// handle that error, and give you back an `Option<T>` instead.
    ///
    /// [`get_result`]: ../prelude/trait.LoadDsl.html#method.get_result
    /// [`first`]: ../prelude/trait.FirstDsl.html#method.first
    ///
    /// # Example
    ///
    /// ```rust
    /// use diesel::result::{QueryResult, Error};
    /// use diesel::OptionalExtension;
    ///
    /// let result: QueryResult<i32> = Ok(1);
    /// assert_eq!(Ok(Some(1)), result.optional());
    ///
    /// let result: QueryResult<i32> = Err(Error::NotFound);
    /// assert_eq!(Ok(None), result.optional());
    /// ```
    fn optional(self) -> Result<Option<T>, Error>;
}

impl<T> OptionalExtension<T> for QueryResult<T> {
    fn optional(self) -> Result<Option<T>, Error> {
        match self {
            Ok(value) => Ok(Some(value)),
            Err(Error::NotFound) => Ok(None),
            Err(e) => Err(e),
        }
    }
}

impl From<NulError> for ConnectionError {
    fn from(e: NulError) -> Self {
        ConnectionError::InvalidCString(e)
    }
}

impl From<NulError> for Error {
    fn from(e: NulError) -> Self {
        Error::InvalidCString(e)
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::InvalidCString(ref nul_err) => nul_err.fmt(f),
            Error::DatabaseError(_, ref e) => write!(f, "{}", e.message()),
            Error::NotFound => f.write_str("NotFound"),
            Error::QueryBuilderError(ref e) => e.fmt(f),
            Error::DeserializationError(ref e) => e.fmt(f),
            Error::SerializationError(ref e) => e.fmt(f),
            Error::RollbackTransaction => write!(f, "{}", self.description()),
            Error::__Nonexhaustive => unreachable!(),
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidCString(ref nul_err) => nul_err.description(),
            Error::DatabaseError(_, ref e) => e.message(),
            Error::NotFound => "Record not found",
            Error::QueryBuilderError(ref e) => e.description(),
            Error::DeserializationError(ref e) => e.description(),
            Error::SerializationError(ref e) => e.description(),
            Error::RollbackTransaction => "The current transaction was aborted",
            Error::__Nonexhaustive => unreachable!(),
        }
    }
}

impl Display for ConnectionError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ConnectionError::InvalidCString(ref nul_err) => nul_err.fmt(f),
            ConnectionError::BadConnection(ref s) => write!(f, "{}", s),
            ConnectionError::InvalidConnectionUrl(ref s) => write!(f, "{}", s),
            ConnectionError::CouldntSetupConfiguration(ref e) => e.fmt(f),
            ConnectionError::__Nonexhaustive => unreachable!(),
        }
    }
}

impl StdError for ConnectionError {
    fn description(&self) -> &str {
        match *self {
            ConnectionError::InvalidCString(ref nul_err) => nul_err.description(),
            ConnectionError::BadConnection(ref s) => s,
            ConnectionError::InvalidConnectionUrl(ref s) => s,
            ConnectionError::CouldntSetupConfiguration(ref e) => e.description(),
            ConnectionError::__Nonexhaustive => unreachable!(),
        }
    }
}

impl PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        match (self, other) {
            (&Error::InvalidCString(ref a), &Error::InvalidCString(ref b)) => a == b,
            (&Error::DatabaseError(_, ref a), &Error::DatabaseError(_, ref b)) => {
                a.message() == b.message()
            }
            (&Error::NotFound, &Error::NotFound) => true,
            _ => false,
        }
    }
}

#[cfg(test)]
#[allow(warnings)]
fn error_impls_send() {
    let err: Error = unimplemented!();
    let x: &Send = &err;
}

pub(crate) fn first_or_not_found<T>(records: QueryResult<Vec<T>>) -> QueryResult<T> {
    records?.into_iter().next().ok_or(Error::NotFound)
}
<|endoftext|>


<commit_before>use lazy_static::lazy_static;
use std::future::Future;
use std::sync::Mutex;
use tokio::runtime::{Builder, Runtime};

lazy_static! {
    static ref RUNTIME: Mutex<Runtime> = Mutex::new(
        Builder::new()
            .basic_scheduler() // Do not make a new thread since this runtime is only used for network requests
            .enable_all()
            .build()
            .unwrap()
    );
}

pub fn blocking<F: Future>(future: F) -> F::Output {
    RUNTIME.lock().unwrap().block_on(future)
}
<commit_msg>enable only I/O reactor for async operations<commit_after>use lazy_static::lazy_static;
use std::future::Future;
use std::sync::Mutex;
use tokio::runtime::{Builder, Runtime};

lazy_static! {
    static ref RUNTIME: Mutex<Runtime> = Mutex::new(
        Builder::new()
            .basic_scheduler() // Do not make a new thread since this runtime is only used for network requests
            .enable_io()
            .build()
            .unwrap()
    );
}

pub fn blocking<F: Future>(future: F) -> F::Output {
    RUNTIME.lock().unwrap().block_on(future)
}
<|endoftext|>


<commit_before>use entities::*;
use std::cmp::Ordering;
use super::geo::{self, Coordinate};

trait DistanceTo {
    fn distance_to(&self, &Coordinate) -> f64;
}

impl DistanceTo for Entry {
    fn distance_to(&self, c: &Coordinate) -> f64 {
        geo::distance(&Coordinate {
                          lat: self.lat,
                          lng: self.lng,
                      },
                      c)
    }
}

pub trait SortByDistanceTo {
    fn sort_by_distance_to(&mut self, &Coordinate);
}

impl SortByDistanceTo for Vec<Entry> {
    fn sort_by_distance_to(&mut self, c: &Coordinate) {
        if !(c.lat.is_finite() && c.lng.is_finite()) {
            return;
        }
        self.sort_by(|a, _|
            if a.lat.is_finite() && a.lng.is_finite() {
                Ordering::Less
            } else {
                warn!("invalid coordinate: {}/{}", a.lat, a.lng);
                Ordering::Greater
            }
        );
        self.sort_by(|a, b| {
            a.distance_to(c).partial_cmp(&b.distance_to(c)).unwrap_or(Ordering::Equal)
        })
    }
}

pub trait Rated {
    fn average_rating(&self, &[Rating], &[Triple]) -> f64;
}

impl Rated for Entry {
    fn average_rating(&self, ratings: &[Rating], triples: &[Triple]) -> f64 {
        let entry_ratings : Vec<(&String, &String)> = triples
            .into_iter()
            .filter_map(|x| match *x {
                Triple {
                    subject   : ObjectId::Entry(ref e_id),
                    predicate : Relation::IsRatedWith,
                    object    : ObjectId::Rating(ref r_id)
                } => Some((e_id, r_id)),
                _ => None
            })
            .filter(|entry_rating| *entry_rating.0 == self.id).collect();

        let avg = ratings
            .into_iter()
            .filter_map(|rating| if entry_ratings.iter().any(|entry_rating| *entry_rating.1 == rating.id) { Some(rating) } else { None })
            .fold(0, |acc, ref rating| acc + rating.value) as f64
            / entry_ratings.len() as f64;

        if !avg.is_nan() {
            avg as f64
        } else {
            0.0
        }
    }
}

pub trait SortByAverageRating {
    fn sort_by_avg_rating(&mut self, &[Rating], &[Triple]);
}

impl SortByAverageRating for Vec<Entry> {
    fn sort_by_avg_rating(&mut self, ratings: &[Rating], triples: &[Triple]){
        self.sort_by(|a, b| {
            b.average_rating(ratings, triples)
            .partial_cmp(&a.average_rating(ratings, triples))
            .unwrap_or(Ordering::Equal)
        })
    }
}

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

    fn new_entry(id: &str, lat: f64, lng: f64) -> Entry {
        Entry{
            id          : id.into(),
            created     : 0,
            version     : 0,
            title       : "foo".into(),
            description : "bar".into(),
            lat         : lat,
            lng         : lng,
            street      : None,
            zip         : None,
            city        : None,
            country     : None,
            email       : None,
            telephone   : None,
            homepage    : None,
            categories  : vec![],
            license     : None,
        }
    }

    fn new_rating(id: &str, value: i8) -> Rating {
        Rating{
            id         : id.into(),
            created    : 0,
            title      : "blubb".into(),
            value      : value.into(),
            context    : RatingContext::Diversity
        }
    }

    #[test]
    fn test_average_rating() {
        let mut entry1 = new_entry("a", 0.0, 0.0);
        let mut entry2 = new_entry("b", 0.0, 0.0);

        let ratings = vec![
            new_rating("1", 0),
            new_rating("2", 0),
            new_rating("3", 3),
            new_rating("4", 3),
            new_rating("5", -3),
            new_rating("6", 3),
        ];

        let triples = vec![
            Triple{subject: ObjectId::Entry("a".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("1".into())},
            Triple{subject: ObjectId::Entry("a".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("2".into())},
            Triple{subject: ObjectId::Entry("a".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("3".into())},
            Triple{subject: ObjectId::Entry("a".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("4".into())},
            Triple{subject: ObjectId::Entry("b".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("5".into())},
            Triple{subject: ObjectId::Entry("b".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("6".into())},
        ];

        assert_eq!(entry1.average_rating(&ratings, &triples), 1.5);
        assert_eq!(entry2.average_rating(&ratings, &triples), 0.0);
    }

    #[test]
    fn test_sort_by_avg_rating(){
        let mut entries = vec![
            new_entry("a", 0.0, 0.0),
            new_entry("b", 0.0, 0.0),
            new_entry("c", 0.0, 0.0),
            new_entry("d", 0.0, 0.0),
            new_entry("e", 0.0, 0.0),
        ];

        let ratings = vec![
            new_rating("1", 0),
            new_rating("2", 10),
            new_rating("3", 3),
            new_rating("4", -1),
            new_rating("5", 0),
        ];

        let triples = vec![
            Triple{subject: ObjectId::Entry("b".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("1".into())},
            Triple{subject: ObjectId::Entry("b".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("2".into())},
            Triple{subject: ObjectId::Entry("c".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("3".into())},
            Triple{subject: ObjectId::Entry("d".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("4".into())},
            Triple{subject: ObjectId::Entry("e".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("5".into())},
        ];

        entries.sort_by_avg_rating(&ratings, &triples);

        assert_eq!(entries[0].id, "b");
        assert_eq!(entries[1].id, "c");
        assert!(entries[2].id == "a" || entries[2].id == "e");
        assert!(entries[3].id == "a" || entries[3].id == "e");
        assert_eq!(entries[4].id, "d");

        // tests:
        // - negative ratings
    }

    #[test]
    fn sort_by_distance() {
        let mut entries = vec![new_entry("a", 1.0, 0.0),
                               new_entry("b", 0.0, 0.0),
                               new_entry("c", 1.0, 1.0),
                               new_entry("d", 0.0, 0.5),
                               new_entry("e", -1.0, -1.0)];
        let x = Coordinate {
            lat: 0.0,
            lng: 0.0,
        };
        entries.sort_by_distance_to(&x);
        assert_eq!(entries[0].id, "b");
        assert_eq!(entries[1].id, "d");
        assert_eq!(entries[2].id, "a");
        assert!(entries[3].id == "c" || entries[3].id == "e");
        assert!(entries[4].id == "c" || entries[4].id == "e");
    }

    use std::f64::{NAN, INFINITY};

    #[test]
    fn sort_with_invalid_coordinates() {
        let mut entries = vec![new_entry("a", 1.0, NAN),
                               new_entry("b", 1.0, INFINITY),
                               new_entry("c", 2.0, 0.0),
                               new_entry("d", NAN, NAN),
                               new_entry("e", 1.0, 0.0)];
        let x = Coordinate {
            lat: 0.0,
            lng: 0.0,
        };
        entries.sort_by_distance_to(&x);
        assert_eq!(entries[0].id, "e");
        assert_eq!(entries[1].id, "c");

        let mut entries =
            vec![new_entry("a", 2.0, 0.0), new_entry("b", 0.0, 0.0), new_entry("c", 1.0, 0.0)];

        let x = Coordinate {
            lat: NAN,
            lng: 0.0,
        };
        entries.sort_by_distance_to(&x);
        assert_eq!(entries[0].id, "a");
        assert_eq!(entries[1].id, "b");
        assert_eq!(entries[2].id, "c");
    }

}
<commit_msg>fix(ranking): test all test cases<commit_after>use entities::*;
use std::cmp::Ordering;
use super::geo::{self, Coordinate};

trait DistanceTo {
    fn distance_to(&self, &Coordinate) -> f64;
}

impl DistanceTo for Entry {
    fn distance_to(&self, c: &Coordinate) -> f64 {
        geo::distance(&Coordinate {
                          lat: self.lat,
                          lng: self.lng,
                      },
                      c)
    }
}

pub trait SortByDistanceTo {
    fn sort_by_distance_to(&mut self, &Coordinate);
}

impl SortByDistanceTo for Vec<Entry> {
    fn sort_by_distance_to(&mut self, c: &Coordinate) {
        if !(c.lat.is_finite() && c.lng.is_finite()) {
            return;
        }
        self.sort_by(|a, _|
            if a.lat.is_finite() && a.lng.is_finite() {
                Ordering::Less
            } else {
                warn!("invalid coordinate: {}/{}", a.lat, a.lng);
                Ordering::Greater
            }
        );
        self.sort_by(|a, b| {
            a.distance_to(c).partial_cmp(&b.distance_to(c)).unwrap_or(Ordering::Equal)
        })
    }
}

pub trait Rated {
    fn average_rating(&self, &[Rating], &[Triple]) -> f64;
}

impl Rated for Entry {
    fn average_rating(&self, ratings: &[Rating], triples: &[Triple]) -> f64 {
        let entry_ratings : Vec<(&String, &String)> = triples
            .into_iter()
            .filter_map(|x| match *x {
                Triple {
                    subject   : ObjectId::Entry(ref e_id),
                    predicate : Relation::IsRatedWith,
                    object    : ObjectId::Rating(ref r_id)
                } => Some((e_id, r_id)),
                _ => None
            })
            .filter(|entry_rating| *entry_rating.0 == self.id).collect();

        let avg = ratings
            .into_iter()
            .filter_map(|rating| if entry_ratings.iter().any(|entry_rating| *entry_rating.1 == rating.id) { Some(rating) } else { None })
            .fold(0, |acc, ref rating| acc + rating.value) as f64
            / entry_ratings.len() as f64;

        if !avg.is_nan() {
            avg as f64
        } else {
            0.0
        }
    }
}

pub trait SortByAverageRating {
    fn sort_by_avg_rating(&mut self, &[Rating], &[Triple]);
}

impl SortByAverageRating for Vec<Entry> {
    fn sort_by_avg_rating(&mut self, ratings: &[Rating], triples: &[Triple]){
        self.sort_by(|a, b| {
            b.average_rating(ratings, triples)
            .partial_cmp(&a.average_rating(ratings, triples))
            .unwrap_or(Ordering::Equal)
        })
    }
}

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

    fn new_entry(id: &str, lat: f64, lng: f64) -> Entry {
        Entry{
            id          : id.into(),
            created     : 0,
            version     : 0,
            title       : "foo".into(),
            description : "bar".into(),
            lat         : lat,
            lng         : lng,
            street      : None,
            zip         : None,
            city        : None,
            country     : None,
            email       : None,
            telephone   : None,
            homepage    : None,
            categories  : vec![],
            license     : None,
        }
    }

    fn new_rating(id: &str, value: i8) -> Rating {
        Rating{
            id         : id.into(),
            created    : 0,
            title      : "blubb".into(),
            value      : value.into(),
            context    : RatingContext::Diversity
        }
    }

    #[test]
    fn test_average_rating() {
        let mut entry1 = new_entry("a", 0.0, 0.0);
        let mut entry2 = new_entry("b", 0.0, 0.0);
        let mut entry3 = new_entry("c", 0.0, 0.0);

        let ratings = vec![
            new_rating("1", 0),
            new_rating("2", 0),
            new_rating("3", 3),
            new_rating("4", 3),
            new_rating("5", -3),
            new_rating("6", 3),
        ];

        let triples = vec![
            Triple{subject: ObjectId::Entry("a".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("1".into())},
            Triple{subject: ObjectId::Entry("a".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("2".into())},
            Triple{subject: ObjectId::Entry("a".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("3".into())},
            Triple{subject: ObjectId::Entry("a".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("4".into())},
            Triple{subject: ObjectId::Entry("b".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("5".into())},
            Triple{subject: ObjectId::Entry("b".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("6".into())},
        ];

        assert_eq!(entry1.average_rating(&ratings, &triples), 1.5);
        assert_eq!(entry2.average_rating(&ratings, &triples), 0.0);
        assert_eq!(entry3.average_rating(&ratings, &triples), 0.0);
    }

    #[test]
    fn test_sort_by_avg_rating(){
        let mut entries = vec![
            new_entry("a", 0.0, 0.0),
            new_entry("b", 0.0, 0.0),
            new_entry("c", 0.0, 0.0),
            new_entry("d", 0.0, 0.0),
            new_entry("e", 0.0, 0.0),
        ];

        let ratings = vec![
            new_rating("1", 0),
            new_rating("2", 10),
            new_rating("3", 3),
            new_rating("4", -1),
            new_rating("5", 0),
        ];

        let triples = vec![
            Triple{subject: ObjectId::Entry("b".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("1".into())},
            Triple{subject: ObjectId::Entry("b".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("2".into())},
            Triple{subject: ObjectId::Entry("c".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("3".into())},
            Triple{subject: ObjectId::Entry("d".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("4".into())},
            Triple{subject: ObjectId::Entry("e".into()), predicate: Relation::IsRatedWith, object: ObjectId::Rating("5".into())},
        ];

        entries.sort_by_avg_rating(&ratings, &triples);

        assert_eq!(entries[0].id, "b");
        assert_eq!(entries[1].id, "c");
        assert!(entries[2].id == "a" || entries[2].id == "e");
        assert!(entries[3].id == "a" || entries[3].id == "e");
        assert_eq!(entries[4].id, "d");

        // tests:
        // - negative ratings
    }

    #[test]
    fn sort_by_distance() {
        let mut entries = vec![new_entry("a", 1.0, 0.0),
                               new_entry("b", 0.0, 0.0),
                               new_entry("c", 1.0, 1.0),
                               new_entry("d", 0.0, 0.5),
                               new_entry("e", -1.0, -1.0)];
        let x = Coordinate {
            lat: 0.0,
            lng: 0.0,
        };
        entries.sort_by_distance_to(&x);
        assert_eq!(entries[0].id, "b");
        assert_eq!(entries[1].id, "d");
        assert_eq!(entries[2].id, "a");
        assert!(entries[3].id == "c" || entries[3].id == "e");
        assert!(entries[4].id == "c" || entries[4].id == "e");
    }

    use std::f64::{NAN, INFINITY};

    #[test]
    fn sort_with_invalid_coordinates() {
        let mut entries = vec![new_entry("a", 1.0, NAN),
                               new_entry("b", 1.0, INFINITY),
                               new_entry("c", 2.0, 0.0),
                               new_entry("d", NAN, NAN),
                               new_entry("e", 1.0, 0.0)];
        let x = Coordinate {
            lat: 0.0,
            lng: 0.0,
        };
        entries.sort_by_distance_to(&x);
        assert_eq!(entries[0].id, "e");
        assert_eq!(entries[1].id, "c");

        let mut entries =
            vec![new_entry("a", 2.0, 0.0), new_entry("b", 0.0, 0.0), new_entry("c", 1.0, 0.0)];

        let x = Coordinate {
            lat: NAN,
            lng: 0.0,
        };
        entries.sort_by_distance_to(&x);
        assert_eq!(entries[0].id, "a");
        assert_eq!(entries[1].id, "b");
        assert_eq!(entries[2].id, "c");
    }

}
<|endoftext|>


<commit_before>use num_complex::Complex;
use num_traits::Zero;

use common::{FFTnum, verify_length, verify_length_divisible};

use algorithm::butterflies::{Butterfly2, Butterfly4, Butterfly8, Butterfly16, FFTButterfly};
use ::{Length, IsInverse, FFT};
use twiddles;

/// FFT algorithm optimized for power-of-two sizes
///
/// ~~~
/// // Computes a forward FFT of size 4096
/// use rustfft::algorithm::Radix4;
/// use rustfft::FFT;
/// use rustfft::num_complex::Complex;
/// use rustfft::num_traits::Zero;
///
/// let mut input:  Vec<Complex<f32>> = vec![Zero::zero(); 4096];
/// let mut output: Vec<Complex<f32>> = vec![Zero::zero(); 4096];
///
/// let fft = Radix4::new(4096, false);
/// fft.process(&mut input, &mut output);
/// ~~~

pub struct Radix4<T> {
    twiddles: Box<[Complex<T>]>,
    butterfly8: Butterfly8<T>,
    butterfly16: Butterfly16<T>,
    len: usize,
    inverse: bool,
}

impl<T: FFTnum> Radix4<T> {
    /// Preallocates necessary arrays and precomputes necessary data to efficiently compute the power-of-two FFT
    pub fn new(len: usize, inverse: bool) -> Self {
        assert!(len.is_power_of_two() && len > 1, "Radix4 algorithm requires a power-of-two input size greater than one. Got {}", len);

        // precompute the twiddle factors this algorithm will use.
        // we're doing the same precomputation of twiddle factors as the mixed radix algorithm where width=4 and height=len/4
        // but mixed radix only does one step and then calls itself recusrively, and this algorithm does every layer all the way down
        // so we're going to pack all the "layers" of twiddle factors into a single array, starting with the bottom and going up
        let num_bits = len.trailing_zeros();
        let mut twiddle_stride = if num_bits%2 == 0 {
            len / 64
        } else {
            len / 32
        };

        let mut twiddle_factors = Vec::with_capacity(len * 2);
        while twiddle_stride > 0 {
            let num_rows = len / (twiddle_stride * 4);
            for i in 0..num_rows {
                for k in 1..4 {
                    let twiddle = twiddles::single_twiddle(i * k * twiddle_stride, len, inverse);
                    twiddle_factors.push(twiddle);
                }
            }
            twiddle_stride >>= 2;
        }

        Radix4 {
            twiddles: twiddle_factors.into_boxed_slice(),
            butterfly8: Butterfly8::new(inverse),
            butterfly16: Butterfly16::new(inverse),
            len: len,
            inverse: inverse,
        }
    }

    fn perform_fft(&self, signal: &[Complex<T>], spectrum: &mut [Complex<T>]) {
        match self.len() {
            2 => {
                spectrum.copy_from_slice(signal);
                unsafe { Butterfly2::new(self.inverse).process_inplace(spectrum) }
            },
            4 => {
                spectrum.copy_from_slice(signal);
                unsafe { Butterfly4::new(self.inverse).process_inplace(spectrum) }
            },
            _ => {
                // copy the data into the spectrum vector
                prepare_radix4(signal.len(), signal, spectrum, 1);

                // perform the butterflies. the butterfly size depends on the input size
                let num_bits = signal.len().trailing_zeros();
                let mut current_size = if num_bits % 2 == 0 {
                    unsafe { self.butterfly16.process_multi_inplace(spectrum) };

                    // for the cross-ffts we want to to start off with a size of 64 (16 * 4)
                    64
                } else {
                    unsafe { self.butterfly8.process_multi_inplace(spectrum) };

                    // for the cross-ffts we want to to start off with a size of 32 (8 * 4)
                    32
                };

                let mut layer_twiddles: &[Complex<T>] = &self.twiddles;

                // now, perform all the cross-FFTs, one "layer" at a time
                while current_size <= signal.len() {
                    let num_rows = signal.len() / current_size;

                    for i in 0..num_rows {
                        unsafe {
                            butterfly_4(&mut spectrum[i * current_size..],
                                        layer_twiddles,
                                        current_size / 4,
                                        self.inverse)
                        }
                    }

                    //skip past all the twiddle factors used in this layer
                    let twiddle_offset = (current_size * 3) / 4;
                    layer_twiddles = &layer_twiddles[twiddle_offset..];

                    current_size *= 4;
                }
            }
        }
    }
}

impl<T: FFTnum> FFT<T> for Radix4<T> {
    fn process(&self, input: &mut [Complex<T>], output: &mut [Complex<T>]) {
        verify_length(input, output, self.len());

        self.perform_fft(input, output);
    }
    fn process_multi(&self, input: &mut [Complex<T>], output: &mut [Complex<T>]) {
        verify_length_divisible(input, output, self.len());

        for (in_chunk, out_chunk) in input.chunks_mut(self.len()).zip(output.chunks_mut(self.len())) {
            self.perform_fft(in_chunk, out_chunk);
        }
    }
}
impl<T> Length for Radix4<T> {
    #[inline(always)]
    fn len(&self) -> usize {
        self.len
    }
}
impl<T> IsInverse for Radix4<T> {
    #[inline(always)]
    fn is_inverse(&self) -> bool {
        self.inverse
    }
}

// after testing an iterative bit reversal algorithm, this recursive algorithm
// was almost an order of magnitude faster at setting up
fn prepare_radix4<T: FFTnum>(size: usize,
                           signal: &[Complex<T>],
                           spectrum: &mut [Complex<T>],
                           stride: usize) {
    match size {
        16 => unsafe {
            for i in 0..16 {
                *spectrum.get_unchecked_mut(i) = *signal.get_unchecked(i * stride);
            }
        },
        8 => unsafe {
            for i in 0..8 {
                *spectrum.get_unchecked_mut(i) = *signal.get_unchecked(i * stride);
            }
        },
        4 => unsafe {
            for i in 0..4 {
                *spectrum.get_unchecked_mut(i) = *signal.get_unchecked(i * stride);
            }
        },
        2 => unsafe {
            for i in 0..2 {
                *spectrum.get_unchecked_mut(i) = *signal.get_unchecked(i * stride);
            }
        },
        _ => {
            for i in 0..4 {
                prepare_radix4(size / 4,
                               &signal[i * stride..],
                               &mut spectrum[i * (size / 4)..],
                               stride * 4);
            }
        }
    }
}

unsafe fn butterfly_4<T: FFTnum>(data: &mut [Complex<T>],
                             twiddles: &[Complex<T>],
                             num_ffts: usize,
                             inverse: bool)
{
    let mut idx = 0usize;
    let mut tw_idx = 0usize;
    let mut scratch: [Complex<T>; 6] = [Zero::zero(); 6];
    for _ in 0..num_ffts {
        scratch[0] = data.get_unchecked(idx + 1 * num_ffts) * twiddles[tw_idx];
        scratch[1] = data.get_unchecked(idx + 2 * num_ffts) * twiddles[tw_idx + 1];
        scratch[2] = data.get_unchecked(idx + 3 * num_ffts) * twiddles[tw_idx + 2];
        scratch[5] = data.get_unchecked(idx) - scratch[1];
        *data.get_unchecked_mut(idx) = data.get_unchecked(idx) + scratch[1];
        scratch[3] = scratch[0] + scratch[2];
        scratch[4] = scratch[0] - scratch[2];
        *data.get_unchecked_mut(idx + 2 * num_ffts) = data.get_unchecked(idx) - scratch[3];
        *data.get_unchecked_mut(idx) = data.get_unchecked(idx) + scratch[3];
        if inverse {
            data.get_unchecked_mut(idx + num_ffts).re = scratch[5].re - scratch[4].im;
            data.get_unchecked_mut(idx + num_ffts).im = scratch[5].im + scratch[4].re;
            data.get_unchecked_mut(idx + 3 * num_ffts).re = scratch[5].re + scratch[4].im;
            data.get_unchecked_mut(idx + 3 * num_ffts).im = scratch[5].im - scratch[4].re;
        } else {
            data.get_unchecked_mut(idx + num_ffts).re = scratch[5].re + scratch[4].im;
            data.get_unchecked_mut(idx + num_ffts).im = scratch[5].im - scratch[4].re;
            data.get_unchecked_mut(idx + 3 * num_ffts).re = scratch[5].re - scratch[4].im;
            data.get_unchecked_mut(idx + 3 * num_ffts).im = scratch[5].im + scratch[4].re;
        }

        tw_idx += 3;
        idx += 1;
    }
}

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

    #[test]
    fn test_radix4() {
        for pow in 1..8 {
            let len = 1 << pow;
            test_radix4_with_length(len, false);
            test_radix4_with_length(len, true);
        }
    }

    fn test_radix4_with_length(len: usize, inverse: bool) {
        let fft = Radix4::new(len, inverse);

        check_fft_algorithm(&fft, len, inverse);
    }
}
<commit_msg>Remove restriction that Radix4 len must be > 1<commit_after>use num_complex::Complex;
use num_traits::Zero;

use common::{FFTnum, verify_length, verify_length_divisible};

use algorithm::butterflies::{Butterfly2, Butterfly4, Butterfly8, Butterfly16, FFTButterfly};
use ::{Length, IsInverse, FFT};
use twiddles;

/// FFT algorithm optimized for power-of-two sizes
///
/// ~~~
/// // Computes a forward FFT of size 4096
/// use rustfft::algorithm::Radix4;
/// use rustfft::FFT;
/// use rustfft::num_complex::Complex;
/// use rustfft::num_traits::Zero;
///
/// let mut input:  Vec<Complex<f32>> = vec![Zero::zero(); 4096];
/// let mut output: Vec<Complex<f32>> = vec![Zero::zero(); 4096];
///
/// let fft = Radix4::new(4096, false);
/// fft.process(&mut input, &mut output);
/// ~~~

pub struct Radix4<T> {
    twiddles: Box<[Complex<T>]>,
    butterfly8: Butterfly8<T>,
    butterfly16: Butterfly16<T>,
    len: usize,
    inverse: bool,
}

impl<T: FFTnum> Radix4<T> {
    /// Preallocates necessary arrays and precomputes necessary data to efficiently compute the power-of-two FFT
    pub fn new(len: usize, inverse: bool) -> Self {
        assert!(len.is_power_of_two(), "Radix4 algorithm requires a power-of-two input size. Got {}", len);

        // precompute the twiddle factors this algorithm will use.
        // we're doing the same precomputation of twiddle factors as the mixed radix algorithm where width=4 and height=len/4
        // but mixed radix only does one step and then calls itself recusrively, and this algorithm does every layer all the way down
        // so we're going to pack all the "layers" of twiddle factors into a single array, starting with the bottom and going up
        let num_bits = len.trailing_zeros();
        let mut twiddle_stride = if num_bits%2 == 0 {
            len / 64
        } else {
            len / 32
        };

        let mut twiddle_factors = Vec::with_capacity(len * 2);
        while twiddle_stride > 0 {
            let num_rows = len / (twiddle_stride * 4);
            for i in 0..num_rows {
                for k in 1..4 {
                    let twiddle = twiddles::single_twiddle(i * k * twiddle_stride, len, inverse);
                    twiddle_factors.push(twiddle);
                }
            }
            twiddle_stride >>= 2;
        }

        Radix4 {
            twiddles: twiddle_factors.into_boxed_slice(),
            butterfly8: Butterfly8::new(inverse),
            butterfly16: Butterfly16::new(inverse),
            len: len,
            inverse: inverse,
        }
    }

    fn perform_fft(&self, signal: &[Complex<T>], spectrum: &mut [Complex<T>]) {
        match self.len() {
            0...1 => spectrum.copy_from_slice(signal),
            2 => {
                spectrum.copy_from_slice(signal);
                unsafe { Butterfly2::new(self.inverse).process_inplace(spectrum) }
            },
            4 => {
                spectrum.copy_from_slice(signal);
                unsafe { Butterfly4::new(self.inverse).process_inplace(spectrum) }
            },
            _ => {
                // copy the data into the spectrum vector
                prepare_radix4(signal.len(), signal, spectrum, 1);

                // perform the butterflies. the butterfly size depends on the input size
                let num_bits = signal.len().trailing_zeros();
                let mut current_size = if num_bits % 2 == 0 {
                    unsafe { self.butterfly16.process_multi_inplace(spectrum) };

                    // for the cross-ffts we want to to start off with a size of 64 (16 * 4)
                    64
                } else {
                    unsafe { self.butterfly8.process_multi_inplace(spectrum) };

                    // for the cross-ffts we want to to start off with a size of 32 (8 * 4)
                    32
                };

                let mut layer_twiddles: &[Complex<T>] = &self.twiddles;

                // now, perform all the cross-FFTs, one "layer" at a time
                while current_size <= signal.len() {
                    let num_rows = signal.len() / current_size;

                    for i in 0..num_rows {
                        unsafe {
                            butterfly_4(&mut spectrum[i * current_size..],
                                        layer_twiddles,
                                        current_size / 4,
                                        self.inverse)
                        }
                    }

                    //skip past all the twiddle factors used in this layer
                    let twiddle_offset = (current_size * 3) / 4;
                    layer_twiddles = &layer_twiddles[twiddle_offset..];

                    current_size *= 4;
                }
            }
        }
    }
}

impl<T: FFTnum> FFT<T> for Radix4<T> {
    fn process(&self, input: &mut [Complex<T>], output: &mut [Complex<T>]) {
        verify_length(input, output, self.len());

        self.perform_fft(input, output);
    }
    fn process_multi(&self, input: &mut [Complex<T>], output: &mut [Complex<T>]) {
        verify_length_divisible(input, output, self.len());

        for (in_chunk, out_chunk) in input.chunks_mut(self.len()).zip(output.chunks_mut(self.len())) {
            self.perform_fft(in_chunk, out_chunk);
        }
    }
}
impl<T> Length for Radix4<T> {
    #[inline(always)]
    fn len(&self) -> usize {
        self.len
    }
}
impl<T> IsInverse for Radix4<T> {
    #[inline(always)]
    fn is_inverse(&self) -> bool {
        self.inverse
    }
}

// after testing an iterative bit reversal algorithm, this recursive algorithm
// was almost an order of magnitude faster at setting up
fn prepare_radix4<T: FFTnum>(size: usize,
                           signal: &[Complex<T>],
                           spectrum: &mut [Complex<T>],
                           stride: usize) {
    match size {
        16 => unsafe {
            for i in 0..16 {
                *spectrum.get_unchecked_mut(i) = *signal.get_unchecked(i * stride);
            }
        },
        8 => unsafe {
            for i in 0..8 {
                *spectrum.get_unchecked_mut(i) = *signal.get_unchecked(i * stride);
            }
        },
        4 => unsafe {
            for i in 0..4 {
                *spectrum.get_unchecked_mut(i) = *signal.get_unchecked(i * stride);
            }
        },
        2 => unsafe {
            for i in 0..2 {
                *spectrum.get_unchecked_mut(i) = *signal.get_unchecked(i * stride);
            }
        },
        _ => {
            for i in 0..4 {
                prepare_radix4(size / 4,
                               &signal[i * stride..],
                               &mut spectrum[i * (size / 4)..],
                               stride * 4);
            }
        }
    }
}

unsafe fn butterfly_4<T: FFTnum>(data: &mut [Complex<T>],
                             twiddles: &[Complex<T>],
                             num_ffts: usize,
                             inverse: bool)
{
    let mut idx = 0usize;
    let mut tw_idx = 0usize;
    let mut scratch: [Complex<T>; 6] = [Zero::zero(); 6];
    for _ in 0..num_ffts {
        scratch[0] = data.get_unchecked(idx + 1 * num_ffts) * twiddles[tw_idx];
        scratch[1] = data.get_unchecked(idx + 2 * num_ffts) * twiddles[tw_idx + 1];
        scratch[2] = data.get_unchecked(idx + 3 * num_ffts) * twiddles[tw_idx + 2];
        scratch[5] = data.get_unchecked(idx) - scratch[1];
        *data.get_unchecked_mut(idx) = data.get_unchecked(idx) + scratch[1];
        scratch[3] = scratch[0] + scratch[2];
        scratch[4] = scratch[0] - scratch[2];
        *data.get_unchecked_mut(idx + 2 * num_ffts) = data.get_unchecked(idx) - scratch[3];
        *data.get_unchecked_mut(idx) = data.get_unchecked(idx) + scratch[3];
        if inverse {
            data.get_unchecked_mut(idx + num_ffts).re = scratch[5].re - scratch[4].im;
            data.get_unchecked_mut(idx + num_ffts).im = scratch[5].im + scratch[4].re;
            data.get_unchecked_mut(idx + 3 * num_ffts).re = scratch[5].re + scratch[4].im;
            data.get_unchecked_mut(idx + 3 * num_ffts).im = scratch[5].im - scratch[4].re;
        } else {
            data.get_unchecked_mut(idx + num_ffts).re = scratch[5].re + scratch[4].im;
            data.get_unchecked_mut(idx + num_ffts).im = scratch[5].im - scratch[4].re;
            data.get_unchecked_mut(idx + 3 * num_ffts).re = scratch[5].re - scratch[4].im;
            data.get_unchecked_mut(idx + 3 * num_ffts).im = scratch[5].im + scratch[4].re;
        }

        tw_idx += 3;
        idx += 1;
    }
}

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

    #[test]
    fn test_radix4() {
        for pow in 0..8 {
            let len = 1 << pow;
            test_radix4_with_length(len, false);
            test_radix4_with_length(len, true);
        }
    }

    fn test_radix4_with_length(len: usize, inverse: bool) {
        let fft = Radix4::new(len, inverse);

        check_fft_algorithm(&fft, len, inverse);
    }
}
<|endoftext|>


<commit_before>use std::collections::btree_map::{BTreeMap, Iter};

use library::Library;
use nameutil::crate_name;
use super::namespaces;
use version::Version;

/// Provides assistance in generating use declarations.
///
/// It takes into account that use declaration referring to names within the
/// same crate will look differently. It also avoids generating spurious
/// declarations referring to names from within the same module as the one we
/// are generating code for.
#[derive(Clone, Debug, Default)]
pub struct Imports {
    /// Name of the current crate.
    crate_name: String,
    /// Name defined within current module. It doesn't need use declaration.
    ///
    /// NOTE: Currently we don't need to support more than one such name.
    defined: Option<String>,
    map: BTreeMap<String, (Option<Version>, Vec<String>)>,
}

impl Imports {
    pub fn new(gir: &Library) -> Imports {
        let crate_name = if gir.namespace(namespaces::MAIN).name == "GObject" {
            crate_name("GLib")
        } else {
            crate_name(&gir.namespace(namespaces::MAIN).name)
        };
        Imports {
            crate_name,
            defined: None,
            map: BTreeMap::new(),
        }
    }

    pub fn with_defined(gir: &Library, name: &str) -> Imports {
        let crate_name = crate_name(&gir.namespace(namespaces::MAIN).name);
        Imports {
            crate_name,
            defined: Some(name.to_owned()),
            map: BTreeMap::new(),
        }
    }

    /// Declares that name should be available through its last path component.
    ///
    /// For example, if name is `X::Y::Z` then it will be available as `Z`.
    pub fn add(&mut self, name: &str, version: Option<Version>) {
        if let Some(ref defined) = self.defined {
            if name == defined {
                return
            }
        }
        if let Some(name) = self.strip_crate_name(name) {
            let entry = self.map.entry(name.to_owned()).or_insert((version, Vec::new()));
            if version < entry.0 {
                *entry = (version, Vec::new());
            } else {
                *entry = (entry.0, Vec::new());
            }
        }
    }

    /// Declares that name should be available through its last path component and provides
    /// an optional feature constraint.
    ///
    /// For example, if name is `X::Y::Z` then it will be available as `Z`.
    pub fn add_with_constraint(&mut self, name: &str, version: Option<Version>, constraint: Option<&str>) {
        if let Some(ref defined) = self.defined {
            if name == defined {
                return
            }
        }
        if let Some(name) = self.strip_crate_name(name) {
            let entry = self.map.entry(name.to_owned()).or_insert((version, Vec::new()));
            if version < entry.0 {
                *entry = (version, Vec::new());
            } else {
                *entry = (entry.0, Vec::new());
            }

            if let Some(constraint) = constraint {
                let constraint = String::from(constraint);
                if !entry.1.contains(&constraint) {
                    entry.1.push(constraint);
                }
            }
        }
    }

    /// Declares that name should be available through its full path.
    ///
    /// For example, if name is `X::Y` then it will be available as `X::Y`.
    pub fn add_used_type(&mut self, used_type: &str, version: Option<Version>) {
        if let Some(i) = used_type.find("::") {
            if i == 0 {
                self.add(&used_type[2..], version);
            } else {
                self.add(&used_type[..i], version);
            }
        } else {
            self.add(used_type, version);
        }
    }

    pub fn add_used_types(&mut self, used_types: &[String], version: Option<Version>) {
        for s in used_types {
            self.add_used_type(s, version);
        }
    }

    /// Tries to strip crate name prefix from given name.
    ///
    /// Returns `None` if name matches crate name exactly. Otherwise returns
    /// name with crate name prefix stripped or full name if there was no match.
    fn strip_crate_name<'a>(&self, name: &'a str) -> Option<&'a str> {
        let prefix = &self.crate_name;
        if !name.starts_with(prefix) {
            return Some(name);
        }
        let rest = &name[prefix.len()..];
        if rest.is_empty() {
            None
        } else if rest.starts_with("::") {
            Some(&rest["::".len()..])
        } else {
            // It was false positive, return the whole name.
            Some(name)
        }
    }

    pub fn iter(&self) -> Iter<String, (Option<Version>, Vec<String>)> {
        self.map.iter()
    }
}
<commit_msg>Fix generating objects uses<commit_after>use std::collections::btree_map::{BTreeMap, Iter};

use library::Library;
use nameutil::crate_name;
use super::namespaces;
use version::Version;

/// Provides assistance in generating use declarations.
///
/// It takes into account that use declaration referring to names within the
/// same crate will look differently. It also avoids generating spurious
/// declarations referring to names from within the same module as the one we
/// are generating code for.
#[derive(Clone, Debug, Default)]
pub struct Imports {
    /// Name of the current crate.
    crate_name: String,
    /// Name defined within current module. It doesn't need use declaration.
    ///
    /// NOTE: Currently we don't need to support more than one such name.
    defined: Option<String>,
    map: BTreeMap<String, (Option<Version>, Vec<String>)>,
}

impl Imports {
    pub fn new(gir: &Library) -> Imports {
        Imports {
            crate_name: make_crate_name(gir),
            defined: None,
            map: BTreeMap::new(),
        }
    }

    pub fn with_defined(gir: &Library, name: &str) -> Imports {
        Imports {
            crate_name: make_crate_name(gir),
            defined: Some(name.to_owned()),
            map: BTreeMap::new(),
        }
    }

    /// Declares that name should be available through its last path component.
    ///
    /// For example, if name is `X::Y::Z` then it will be available as `Z`.
    pub fn add(&mut self, name: &str, version: Option<Version>) {
        if let Some(ref defined) = self.defined {
            if name == defined {
                return
            }
        }
        if let Some(name) = self.strip_crate_name(name) {
            let entry = self.map.entry(name.to_owned()).or_insert((version, Vec::new()));
            if version < entry.0 {
                *entry = (version, Vec::new());
            } else {
                *entry = (entry.0, Vec::new());
            }
        }
    }

    /// Declares that name should be available through its last path component and provides
    /// an optional feature constraint.
    ///
    /// For example, if name is `X::Y::Z` then it will be available as `Z`.
    pub fn add_with_constraint(&mut self, name: &str, version: Option<Version>, constraint: Option<&str>) {
        if let Some(ref defined) = self.defined {
            if name == defined {
                return
            }
        }
        if let Some(name) = self.strip_crate_name(name) {
            let entry = self.map.entry(name.to_owned()).or_insert((version, Vec::new()));
            if version < entry.0 {
                *entry = (version, Vec::new());
            } else {
                *entry = (entry.0, Vec::new());
            }

            if let Some(constraint) = constraint {
                let constraint = String::from(constraint);
                if !entry.1.contains(&constraint) {
                    entry.1.push(constraint);
                }
            }
        }
    }

    /// Declares that name should be available through its full path.
    ///
    /// For example, if name is `X::Y` then it will be available as `X::Y`.
    pub fn add_used_type(&mut self, used_type: &str, version: Option<Version>) {
        if let Some(i) = used_type.find("::") {
            if i == 0 {
                self.add(&used_type[2..], version);
            } else {
                self.add(&used_type[..i], version);
            }
        } else {
            self.add(used_type, version);
        }
    }

    pub fn add_used_types(&mut self, used_types: &[String], version: Option<Version>) {
        for s in used_types {
            self.add_used_type(s, version);
        }
    }

    /// Tries to strip crate name prefix from given name.
    ///
    /// Returns `None` if name matches crate name exactly. Otherwise returns
    /// name with crate name prefix stripped or full name if there was no match.
    fn strip_crate_name<'a>(&self, name: &'a str) -> Option<&'a str> {
        let prefix = &self.crate_name;
        if !name.starts_with(prefix) {
            return Some(name);
        }
        let rest = &name[prefix.len()..];
        if rest.is_empty() {
            None
        } else if rest.starts_with("::") {
            Some(&rest["::".len()..])
        } else {
            // It was false positive, return the whole name.
            Some(name)
        }
    }

    pub fn iter(&self) -> Iter<String, (Option<Version>, Vec<String>)> {
        self.map.iter()
    }
}

fn make_crate_name(gir: &Library) -> String {
    let name = gir.namespace(namespaces::MAIN).name.as_str();
    if name == "GObject" {
        crate_name("GLib")
    } else {
        crate_name(name)
    }
}
<|endoftext|>


<commit_before>/*
 * PCG Random Number Generation for Rust
 *
 * Copyright 2015 John Brooks <robojeb@robojeb.xyz>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

/// Extended PCG generators utilize a simple method to dramatically extend the
/// period of the genrators. In addition to extending the period of the
/// generator it ensures that the generators have K-dimensional
/// equidistribution. This means that the generator will produce every possible
/// K-tuple uniformly.
///
/// These extended generators are currently in a beta state. They are
/// implemented according to my understanding of the generator extension
/// technique presented in the PCG paper.
/// You can use these generators if you want, and if you would like to help
/// me review the code and determine if my implementation is correct that would
/// be wonderful.
pub mod extsizes;

pub use self::extsizes::*;

use extprim::u128::u128;
use rand::{Rng, Rand, SeedableRng};
use std::marker::PhantomData;
use super::PcgEngine;
use super::numops::*;
use super::stream::*;
use super::outputmix::*;
use super::multiplier::*;

/// An extended PCG generator. These generators provide K-dimensional
/// equidistribution. Where K is specified by the value of the Size parameter
/// which must be an ExtSize type.
pub struct ExtPcg<Itype, Xtype,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
    Size: ExtSize>
{
    pcg : PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>,
    ext : Vec<Xtype>,
    _size : PhantomData<Size>,
}

impl<Itype, Xtype, StreamMix, MulMix, OutMix, Size>
    ExtPcg<Itype, Xtype, StreamMix, MulMix, OutMix, Size>
    where Itype: PcgOps + BitSize + AsSmaller<Xtype> + Clone,
    Xtype: PcgOps + BitSize + Rand,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
    Size: ExtSize {

    /// Create a new ExtPcg from an existing PCG. This will consume
    /// Size random values to initialize the extension array.
    pub fn from_pcg(pcg: PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>) ->
        ExtPcg<Itype, Xtype, StreamMix, MulMix, OutMix, Size>
        where PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>: Rng {
            let mut pcg = pcg;

            //Create the starting extension array
            let mut ext = Vec::new();
            for _ in 0..Size::ext_size() {
                ext.push(pcg.gen());
            }

            ExtPcg {
                pcg : pcg,
                ext : ext,
                _size : PhantomData::<Size>,
            }
    }

    /// Create a new unseeded ExtPcg.
    pub fn new_unseeded() -> ExtPcg<Itype, Xtype, StreamMix, MulMix, OutMix, Size>
    where PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>: Rng
    {
        let pcg = PcgEngine::<Itype, Xtype, StreamMix, MulMix, OutMix>::new_unseeded();
        Self::from_pcg(pcg)
    }
}

impl<Itype, StreamMix, MulMix, OutMix, Size> Rng for
    ExtPcg<Itype, u32, StreamMix, MulMix, OutMix, Size>
    where Itype: PcgOps + BitSize + AsSmaller<u32> + Clone,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, u32>,
    Size: ExtSize {

    #[inline]
    fn next_u32(&mut self) -> u32 {
        use std::mem::size_of;
        let oldstate = self.pcg.state.clone();
        self.pcg.state = self.pcg.stream_mix.increment().add(oldstate.mul(MulMix::multiplier()));
        let shift = size_of::<usize>() - Size::ext_bits();

        let mask = 2usize.pow(Size::ext_bits() as u32)-1;
        let pick = self.pcg.state.usize() & mask;

        let ext_val = self.ext[pick];
        self.ext[pick] = self.ext[pick] + 1;
        OutMix::output(oldstate) ^ ext_val
    }
}

impl<Itype, StreamMix, MulMix, OutMix, Size> Rng for
    ExtPcg<Itype, u64, StreamMix, MulMix, OutMix, Size>
    where Itype: PcgOps + BitSize + AsSmaller<u64> + Clone,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, u64>,
    Size: ExtSize {

    #[inline]
    fn next_u32(&mut self) -> u32 {
        self.next_u64() as u32
    }

    #[inline]
    fn next_u64(&mut self) -> u64 {
        use std::mem::size_of;
        let oldstate = self.pcg.state.clone();
        self.pcg.state = self.pcg.stream_mix.increment().add(oldstate.mul(MulMix::multiplier()));

        let mask = 2usize.pow(Size::ext_bits() as u32)-1;
        let pick = self.pcg.state.usize() & mask;

        let ext_val = self.ext[pick];
        self.ext[pick] = self.ext[pick] + 1;
        OutMix::output(oldstate) ^ ext_val
    }
}

pub type SetseqXshRr6432ext<Size> = ExtPcg<u64, u32, SpecificSeqStream<u64>, DefaultMultiplier, XshRrMixin, Size>;
pub type SetseqXshRr12832ext<Size> = ExtPcg<u128, u32, SpecificSeqStream<u128>, DefaultMultiplier, XshRrMixin, Size>;
pub type SetseqXshRr12864ext<Size> = ExtPcg<u128, u64, SpecificSeqStream<u128>, DefaultMultiplier, XshRrMixin, Size>;

/// The extended version of the Pcg32 generator
pub type Pcg32Ext<Size> = SetseqXshRr6432ext<Size>;
/// The extended version of the Pcg32L generator
pub type Pcg32LExt<Size> = SetseqXshRr12832ext<Size>;
/// The extended version of the Pcg64 generator
pub type Pcg64Ext<Size> = SetseqXshRr12864ext<Size>;

//
// Seeding for the ExtPcgs
//

//These generics get pretty insane
impl<Itype, Xtype, StreamMix, MulMix, OutMix, Size> SeedableRng<Itype> for ExtPcg<Itype, Xtype, StreamMix, MulMix, OutMix, Size>
    where
    Itype: PcgOps + BitSize + Clone + AsSmaller<Xtype>,
    Xtype: PcgOps + BitSize + Rand,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
    Size: ExtSize, ExtPcg<Itype, Xtype, StreamMix, MulMix, OutMix, Size> : Rng,
    PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix> : Rng + SeedableRng<Itype>

{
    fn reseed(&mut self, seed: Itype) {
        //Update the PCG
        self.pcg.reseed(seed);

        //Update the extension array
        for i in 0..Size::ext_size() {
            self.ext[i] = self.pcg.gen();
        }
    }

    fn from_seed(seed: Itype) -> Self {
        let pcg = PcgEngine::from_seed(seed);
        ExtPcg::from_pcg(pcg)
    }
}

impl<Itype, Xtype,MulMix, OutMix, Size> SeedableRng<[Itype; 2]> for ExtPcg<Itype, Xtype, SpecificSeqStream<Itype>, MulMix, OutMix, Size>
    where
    Itype: PcgOps + BitSize + Clone + AsSmaller<Xtype>,
    Xtype: PcgOps + BitSize + Rand,
    SpecificSeqStream<Itype>: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
    Size: ExtSize, ExtPcg<Itype, Xtype, SpecificSeqStream<Itype>, MulMix, OutMix, Size> : Rng,
    PcgEngine<Itype, Xtype, SpecificSeqStream<Itype>, MulMix, OutMix> : Rng + SeedableRng<[Itype; 2]>

{
    fn reseed(&mut self, seed: [Itype; 2]) {
        //Update the PCG
        self.pcg.reseed(seed);

        //Update the extension array
        for i in 0..Size::ext_size() {
            self.ext[i] = self.pcg.gen();
        }
    }

    fn from_seed(seed: [Itype; 2]) -> Self {
        let pcg = PcgEngine::from_seed(seed);
        ExtPcg::from_pcg(pcg)
    }
}

impl<Xtype, StreamMix, MulMix, OutMix, Size> SeedableRng<[u64; 2]> for ExtPcg<u128, Xtype, StreamMix, MulMix, OutMix, Size>
    where
    u128: PcgOps + BitSize + Clone + AsSmaller<Xtype>,
    Xtype: PcgOps + BitSize + Rand,
    StreamMix: Stream<u128>,
    MulMix: Multiplier<u128>,
    OutMix: OutputMixin<u128, Xtype>,
    Size: ExtSize, ExtPcg<u128, Xtype, StreamMix, MulMix, OutMix, Size> : Rng,
    PcgEngine<u128, Xtype, StreamMix, MulMix, OutMix> : Rng + SeedableRng<[u64; 2]>

{
    fn reseed(&mut self, seed: [u64; 2]) {
        //Update the PCG
        self.pcg.reseed(seed);

        //Update the extension array
        for i in 0..Size::ext_size() {
            self.ext[i] = self.pcg.gen();
        }
    }

    fn from_seed(seed: [u64; 2]) -> Self {
        let pcg = PcgEngine::from_seed(seed);
        ExtPcg::from_pcg(pcg)
    }
}

impl<Xtype,MulMix, OutMix, Size> SeedableRng<[u64; 4]> for ExtPcg<u128, Xtype, SpecificSeqStream<u128>, MulMix, OutMix, Size>
    where
    u128: AsSmaller<Xtype>,
    Xtype: PcgOps + BitSize + Rand,
    SpecificSeqStream<u128>: Stream<u128>,
    MulMix: Multiplier<u128>,
    OutMix: OutputMixin<u128, Xtype>,
    Size: ExtSize, ExtPcg<u128, Xtype, SpecificSeqStream<u128>, MulMix, OutMix, Size> : Rng,
    PcgEngine<u128, Xtype, SpecificSeqStream<u128>, MulMix, OutMix> : Rng + SeedableRng<[u64; 4]>

{
    fn reseed(&mut self, seed: [u64; 4]) {
        //Update the PCG
        self.pcg.reseed(seed);

        //Update the extension array
        for i in 0..Size::ext_size() {
            self.ext[i] = self.pcg.gen();
        }
    }

    fn from_seed(seed: [u64; 4]) -> Self {
        let pcg = PcgEngine::from_seed(seed);
        ExtPcg::from_pcg(pcg)
    }
}
<commit_msg>added some doc info<commit_after>/*
 * PCG Random Number Generation for Rust
 *
 * Copyright 2015 John Brooks <robojeb@robojeb.xyz>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

/// Extended PCG generators utilize a simple method to dramatically extend the
/// period of the genrators. In addition to extending the period of the
/// generator it ensures that the generators have K-dimensional
/// equidistribution. This means that the generator will produce every possible
/// K-tuple uniformly.
///
/// These generators require `K*sizeof(Isize)` extra bytes to provide their
/// equidistribution.
///
/// These extended generators are currently in a beta state. They are
/// implemented according to my understanding of the generator extension
/// technique presented in the PCG paper.
/// You can use these generators if you want, and if you would like to help
/// me review the code and determine if my implementation is correct that would
/// be wonderful.
pub mod extsizes;

pub use self::extsizes::*;

use extprim::u128::u128;
use rand::{Rng, Rand, SeedableRng};
use std::marker::PhantomData;
use super::PcgEngine;
use super::numops::*;
use super::stream::*;
use super::outputmix::*;
use super::multiplier::*;

/// An extended PCG generator. These generators provide K-dimensional
/// equidistribution. Where K is specified by the value of the Size parameter
/// which must be an ExtSize type.
pub struct ExtPcg<Itype, Xtype,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
    Size: ExtSize>
{
    pcg : PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>,
    ext : Vec<Xtype>,
    _size : PhantomData<Size>,
}

impl<Itype, Xtype, StreamMix, MulMix, OutMix, Size>
    ExtPcg<Itype, Xtype, StreamMix, MulMix, OutMix, Size>
    where Itype: PcgOps + BitSize + AsSmaller<Xtype> + Clone,
    Xtype: PcgOps + BitSize + Rand,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
    Size: ExtSize {

    /// Create a new ExtPcg from an existing PCG. This will consume
    /// Size random values to initialize the extension array.
    pub fn from_pcg(pcg: PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>) ->
        ExtPcg<Itype, Xtype, StreamMix, MulMix, OutMix, Size>
        where PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>: Rng {
            let mut pcg = pcg;

            //Create the starting extension array
            let mut ext = Vec::new();
            for _ in 0..Size::ext_size() {
                ext.push(pcg.gen());
            }

            ExtPcg {
                pcg : pcg,
                ext : ext,
                _size : PhantomData::<Size>,
            }
    }

    /// Create a new unseeded ExtPcg.
    pub fn new_unseeded() -> ExtPcg<Itype, Xtype, StreamMix, MulMix, OutMix, Size>
    where PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>: Rng
    {
        let pcg = PcgEngine::<Itype, Xtype, StreamMix, MulMix, OutMix>::new_unseeded();
        Self::from_pcg(pcg)
    }
}

impl<Itype, StreamMix, MulMix, OutMix, Size> Rng for
    ExtPcg<Itype, u32, StreamMix, MulMix, OutMix, Size>
    where Itype: PcgOps + BitSize + AsSmaller<u32> + Clone,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, u32>,
    Size: ExtSize {

    #[inline]
    fn next_u32(&mut self) -> u32 {
        use std::mem::size_of;
        let oldstate = self.pcg.state.clone();
        self.pcg.state = self.pcg.stream_mix.increment().add(oldstate.mul(MulMix::multiplier()));
        let shift = size_of::<usize>() - Size::ext_bits();

        let mask = 2usize.pow(Size::ext_bits() as u32)-1;
        let pick = self.pcg.state.usize() & mask;

        let ext_val = self.ext[pick];
        self.ext[pick] = self.ext[pick] + 1;
        OutMix::output(oldstate) ^ ext_val
    }
}

impl<Itype, StreamMix, MulMix, OutMix, Size> Rng for
    ExtPcg<Itype, u64, StreamMix, MulMix, OutMix, Size>
    where Itype: PcgOps + BitSize + AsSmaller<u64> + Clone,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, u64>,
    Size: ExtSize {

    #[inline]
    fn next_u32(&mut self) -> u32 {
        self.next_u64() as u32
    }

    #[inline]
    fn next_u64(&mut self) -> u64 {
        use std::mem::size_of;
        let oldstate = self.pcg.state.clone();
        self.pcg.state = self.pcg.stream_mix.increment().add(oldstate.mul(MulMix::multiplier()));

        let mask = 2usize.pow(Size::ext_bits() as u32)-1;
        let pick = self.pcg.state.usize() & mask;

        let ext_val = self.ext[pick];
        self.ext[pick] = self.ext[pick] + 1;
        OutMix::output(oldstate) ^ ext_val
    }
}

pub type SetseqXshRr6432ext<Size> = ExtPcg<u64, u32, SpecificSeqStream<u64>, DefaultMultiplier, XshRrMixin, Size>;
pub type SetseqXshRr12832ext<Size> = ExtPcg<u128, u32, SpecificSeqStream<u128>, DefaultMultiplier, XshRrMixin, Size>;
pub type SetseqXshRr12864ext<Size> = ExtPcg<u128, u64, SpecificSeqStream<u128>, DefaultMultiplier, XshRrMixin, Size>;

/// The extended version of the Pcg32 generator
pub type Pcg32Ext<Size> = SetseqXshRr6432ext<Size>;
/// The extended version of the Pcg32L generator
pub type Pcg32LExt<Size> = SetseqXshRr12832ext<Size>;
/// The extended version of the Pcg64 generator
pub type Pcg64Ext<Size> = SetseqXshRr12864ext<Size>;

//
// Seeding for the ExtPcgs
//

//These generics get pretty insane
impl<Itype, Xtype, StreamMix, MulMix, OutMix, Size> SeedableRng<Itype> for ExtPcg<Itype, Xtype, StreamMix, MulMix, OutMix, Size>
    where
    Itype: PcgOps + BitSize + Clone + AsSmaller<Xtype>,
    Xtype: PcgOps + BitSize + Rand,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
    Size: ExtSize, ExtPcg<Itype, Xtype, StreamMix, MulMix, OutMix, Size> : Rng,
    PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix> : Rng + SeedableRng<Itype>

{
    fn reseed(&mut self, seed: Itype) {
        //Update the PCG
        self.pcg.reseed(seed);

        //Update the extension array
        for i in 0..Size::ext_size() {
            self.ext[i] = self.pcg.gen();
        }
    }

    fn from_seed(seed: Itype) -> Self {
        let pcg = PcgEngine::from_seed(seed);
        ExtPcg::from_pcg(pcg)
    }
}

impl<Itype, Xtype,MulMix, OutMix, Size> SeedableRng<[Itype; 2]> for ExtPcg<Itype, Xtype, SpecificSeqStream<Itype>, MulMix, OutMix, Size>
    where
    Itype: PcgOps + BitSize + Clone + AsSmaller<Xtype>,
    Xtype: PcgOps + BitSize + Rand,
    SpecificSeqStream<Itype>: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
    Size: ExtSize, ExtPcg<Itype, Xtype, SpecificSeqStream<Itype>, MulMix, OutMix, Size> : Rng,
    PcgEngine<Itype, Xtype, SpecificSeqStream<Itype>, MulMix, OutMix> : Rng + SeedableRng<[Itype; 2]>

{
    fn reseed(&mut self, seed: [Itype; 2]) {
        //Update the PCG
        self.pcg.reseed(seed);

        //Update the extension array
        for i in 0..Size::ext_size() {
            self.ext[i] = self.pcg.gen();
        }
    }

    fn from_seed(seed: [Itype; 2]) -> Self {
        let pcg = PcgEngine::from_seed(seed);
        ExtPcg::from_pcg(pcg)
    }
}

impl<Xtype, StreamMix, MulMix, OutMix, Size> SeedableRng<[u64; 2]> for ExtPcg<u128, Xtype, StreamMix, MulMix, OutMix, Size>
    where
    u128: PcgOps + BitSize + Clone + AsSmaller<Xtype>,
    Xtype: PcgOps + BitSize + Rand,
    StreamMix: Stream<u128>,
    MulMix: Multiplier<u128>,
    OutMix: OutputMixin<u128, Xtype>,
    Size: ExtSize, ExtPcg<u128, Xtype, StreamMix, MulMix, OutMix, Size> : Rng,
    PcgEngine<u128, Xtype, StreamMix, MulMix, OutMix> : Rng + SeedableRng<[u64; 2]>

{
    fn reseed(&mut self, seed: [u64; 2]) {
        //Update the PCG
        self.pcg.reseed(seed);

        //Update the extension array
        for i in 0..Size::ext_size() {
            self.ext[i] = self.pcg.gen();
        }
    }

    fn from_seed(seed: [u64; 2]) -> Self {
        let pcg = PcgEngine::from_seed(seed);
        ExtPcg::from_pcg(pcg)
    }
}

impl<Xtype,MulMix, OutMix, Size> SeedableRng<[u64; 4]> for ExtPcg<u128, Xtype, SpecificSeqStream<u128>, MulMix, OutMix, Size>
    where
    u128: AsSmaller<Xtype>,
    Xtype: PcgOps + BitSize + Rand,
    SpecificSeqStream<u128>: Stream<u128>,
    MulMix: Multiplier<u128>,
    OutMix: OutputMixin<u128, Xtype>,
    Size: ExtSize, ExtPcg<u128, Xtype, SpecificSeqStream<u128>, MulMix, OutMix, Size> : Rng,
    PcgEngine<u128, Xtype, SpecificSeqStream<u128>, MulMix, OutMix> : Rng + SeedableRng<[u64; 4]>

{
    fn reseed(&mut self, seed: [u64; 4]) {
        //Update the PCG
        self.pcg.reseed(seed);

        //Update the extension array
        for i in 0..Size::ext_size() {
            self.ext[i] = self.pcg.gen();
        }
    }

    fn from_seed(seed: [u64; 4]) -> Self {
        let pcg = PcgEngine::from_seed(seed);
        ExtPcg::from_pcg(pcg)
    }
}
<|endoftext|>


<commit_before>// Copyright © 2018, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate csv;
extern crate geo;
#[macro_use]
extern crate log;
extern crate mimir;
extern crate mimirsbrunn;
#[macro_use]
extern crate serde_derive;
extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use std::path::Path;
use mimir::rubber::Rubber;
use mimir::objects::{Addr, MimirObject};
use mimirsbrunn::admin_geofinder::AdminGeoFinder;
use std::fs;
use structopt::StructOpt;

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub struct OpenAddresse {
    pub id: String,
    pub street: String,
    pub postcode: String,
    pub district: String,
    pub region: String,
    pub city: String,
    pub number: String,
    pub unit: String,
    pub lat: f64,
    pub lon: f64,
}

impl OpenAddresse {
    pub fn into_addr(self, admins_geofinder: &AdminGeoFinder, city_level: u32) -> mimir::Addr {
        let street_name = format!("{} ({})", self.street, self.city);
        let addr_name = format!("{} {}", self.number, self.street);
        let addr_label = format!("{} ({})", addr_name, self.city);
        let street_id = format!("street:{}", self.id); // TODO check if thats ok
        let admins = admins_geofinder.get(&geo::Coordinate {
            x: self.lat,
            y: self.lon,
        });

        let weight = admins
            .iter()
            .find(|a| a.level == city_level)
            .map_or(0., |a| a.weight.get());

        let street = mimir::Street {
            id: street_id,
            street_name: self.street,
            label: street_name.to_string(),
            administrative_regions: admins,
            weight: weight,
            zip_codes: vec![self.postcode.clone()],
            coord: mimir::Coord::new(self.lat, self.lon),
        };
        mimir::Addr {
            id: format!("addr:{};{}", self.lon, self.lat),
            house_number: self.number,
            street: street,
            label: addr_label,
            coord: mimir::Coord::new(self.lat, self.lon),
            weight: weight,
            zip_codes: vec![self.postcode.clone()],
        }
    }
}

fn index_oa<I>(cnx_string: &str, dataset: &str, city_level: u32, files: I)
where
    I: Iterator<Item = std::path::PathBuf>,
{
    let mut rubber = Rubber::new(cnx_string);

    let admins = rubber
        .get_admins_from_dataset(dataset)
        .unwrap_or_else(|err| {
            info!(
                "Administratives regions not found in es db for dataset {}. (error: {})",
                dataset, err
            );
            vec![]
        });
    let admins_geofinder = admins.into_iter().collect();

    let addr_index = rubber.make_index(Addr::doc_type(), dataset).unwrap();
    info!("Add data in elasticsearch db.");
    for f in files {
        info!("importing {:?}...", &f);
        let mut rdr = csv::ReaderBuilder::new()
            .has_headers(true)
            .from_path(&f)
            .unwrap();
        let iter = rdr.deserialize().filter_map(|r| {
            r.map_err(|e| info!("impossible to read line, error: {}", e))
                .ok()
                .map(|v: OpenAddresse| v.into_addr(&admins_geofinder, city_level))
        });
        match rubber.bulk_index(&addr_index, iter) {
            Err(e) => panic!("failed to bulk insert file {:?} because: {}", &f, e),
            Ok(nb) => info!("importing {:?}: {} addresses added.", &f, nb),
        }
    }
    rubber
        .publish_index(Addr::doc_type(), dataset, addr_index, Addr::is_geo_data())
        .unwrap();
}

#[derive(StructOpt, Debug)]
struct Args {
    /// openaddresses files. Can be either a directory or a file.
    #[structopt(short = "i", long = "input")]
    input: String,
    /// Elasticsearch parameters.
    #[structopt(short = "c", long = "connection-string",
                default_value = "http://localhost:9200/munin")]
    connection_string: String,
    /// Name of the dataset.
    #[structopt(short = "d", long = "dataset", default_value = "fr")]
    dataset: String,
    /// City level to  calculate weight.
    #[structopt(short = "C", long = "city-level", default_value = "8")]
    city_level: u32,
}

fn main() {
    mimir::logger_init().unwrap();
    info!("importing open addresses into Mimir");

    let args = Args::from_args();

    let file_path = Path::new(&args.input);
    if file_path.is_dir() {
        let paths: std::fs::ReadDir = fs::read_dir(&args.input).unwrap();
        index_oa(
            &args.connection_string,
            &args.dataset,
            args.city_level,
            paths.map(|p| p.unwrap().path()),
        );
    } else {
        index_oa(
            &args.connection_string,
            &args.dataset,
            args.city_level,
            std::iter::once(std::path::PathBuf::from(&args.input)),
        );
    }
}
<commit_msg>fix after rebase<commit_after>// Copyright © 2018, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate csv;
extern crate geo;
#[macro_use]
extern crate log;
extern crate mimir;
extern crate mimirsbrunn;
#[macro_use]
extern crate serde_derive;
extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use std::path::Path;
use mimir::rubber::Rubber;
use mimir::objects::{Addr, MimirObject};
use mimirsbrunn::admin_geofinder::AdminGeoFinder;
use std::fs;
use structopt::StructOpt;

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub struct OpenAddresse {
    pub id: String,
    pub street: String,
    pub postcode: String,
    pub district: String,
    pub region: String,
    pub city: String,
    pub number: String,
    pub unit: String,
    pub lat: f64,
    pub lon: f64,
}

impl OpenAddresse {
    pub fn into_addr(self, admins_geofinder: &AdminGeoFinder, city_level: u32) -> mimir::Addr {
        let street_name = format!("{} ({})", self.street, self.city);
        let addr_name = format!("{} {}", self.number, self.street);
        let addr_label = format!("{} ({})", addr_name, self.city);
        let street_id = format!("street:{}", self.id); // TODO check if thats ok
        let admins = admins_geofinder.get(&geo::Coordinate {
            x: self.lat,
            y: self.lon,
        });

        let weight = admins
            .iter()
            .find(|a| a.level == city_level)
            .map_or(0., |a| a.weight.get());

        let street = mimir::Street {
            id: street_id,
            street_name: self.street,
            label: street_name.to_string(),
            administrative_regions: admins,
            weight: weight,
            zip_codes: vec![self.postcode.clone()],
            coord: mimir::Coord::new(self.lat, self.lon),
        };
        mimir::Addr {
            id: format!("addr:{};{}", self.lon, self.lat),
            house_number: self.number,
            street: street,
            label: addr_label,
            coord: mimir::Coord::new(self.lat, self.lon),
            weight: weight,
            zip_codes: vec![self.postcode.clone()],
        }
    }
}

fn index_oa<I>(cnx_string: &str, dataset: &str, city_level: u32, files: I)
where
    I: Iterator<Item = std::path::PathBuf>,
{
    let mut rubber = Rubber::new(cnx_string);

    let admins = rubber
        .get_admins_from_dataset(dataset)
        .unwrap_or_else(|err| {
            info!(
                "Administratives regions not found in es db for dataset {}. (error: {})",
                dataset, err
            );
            vec![]
        });
    let admins_geofinder = admins.into_iter().collect();

    let addr_index = rubber.make_index(Addr::doc_type(), dataset).unwrap();
    info!("Add data in elasticsearch db.");
    for f in files {
        info!("importing {:?}...", &f);
        let mut rdr = csv::ReaderBuilder::new()
            .has_headers(true)
            .from_path(&f)
            .unwrap();
        let iter = rdr.deserialize().filter_map(|r| {
            r.map_err(|e| info!("impossible to read line, error: {}", e))
                .ok()
                .map(|v: OpenAddresse| v.into_addr(&admins_geofinder, city_level))
        });
        match rubber.bulk_index(&addr_index, iter) {
            Err(e) => panic!("failed to bulk insert file {:?} because: {}", &f, e),
            Ok(nb) => info!("importing {:?}: {} addresses added.", &f, nb),
        }
    }
    rubber
        .publish_index(Addr::doc_type(), dataset, addr_index, Addr::is_geo_data())
        .unwrap();
}

#[derive(StructOpt, Debug)]
struct Args {
    /// openaddresses files. Can be either a directory or a file.
    #[structopt(short = "i", long = "input")]
    input: String,
    /// Elasticsearch parameters.
    #[structopt(short = "c", long = "connection-string",
                default_value = "http://localhost:9200/munin")]
    connection_string: String,
    /// Name of the dataset.
    #[structopt(short = "d", long = "dataset", default_value = "fr")]
    dataset: String,
    /// City level to  calculate weight.
    #[structopt(short = "C", long = "city-level", default_value = "8")]
    city_level: u32,
}

fn main() {
    mimir::logger_init();
    info!("importing open addresses into Mimir");

    let args = Args::from_args();

    let file_path = Path::new(&args.input);
    if file_path.is_dir() {
        let paths: std::fs::ReadDir = fs::read_dir(&args.input).unwrap();
        index_oa(
            &args.connection_string,
            &args.dataset,
            args.city_level,
            paths.map(|p| p.unwrap().path()),
        );
    } else {
        index_oa(
            &args.connection_string,
            &args.dataset,
            args.city_level,
            std::iter::once(std::path::PathBuf::from(&args.input)),
        );
    }
}
<|endoftext|>