<commit_before>#![feature(macro_rules, plugin_registrar, quote, phase)]

#[phase(plugin, link)]
extern crate syntax;
#[phase(plugin, link)]
extern crate rustc;

use syntax::ast;
use rustc::lint::LintPassObject;
use rustc::plugin::Registry;
use rustc::lint::{Context, LintPass, LintArray};
use rustc::middle::def;
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::visit::FnKind;

declare_lint!(EXCESSIVE_BOOL_USAGE_STRUCTS, Warn,
              "Warn about exessive use of boolean members in structs.")
declare_lint!(EXCESSIVE_BOOL_USAGE_FUNCS, Warn,
              "Warn about exessive use of boolean arguments in functions.")

struct Pass;

fn node_is_bool(cx: &Context, ty: &ast::Ty) -> bool {
    match ty.node {
        ast::TyPath(_, _, id) => {
            match cx.tcx.def_map.borrow().get_copy(&id) {
                def::DefPrimTy(ast::TyBool) => true,
                _ => false,
            }
        },
        _ => false,
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(EXCESSIVE_BOOL_USAGE_STRUCTS, EXCESSIVE_BOOL_USAGE_FUNCS)
    }

    fn check_struct_def(&mut self, cx: &Context, def: &ast::StructDef,
            _: ast::Ident, _: &ast::Generics, id: ast::NodeId) {
        let mut bools = vec![];
        let mut spans = vec![];

        for field in def.fields.iter() {
            if node_is_bool(cx, &*field.node.ty) {
                match field.node {
                    ast::StructField_ { kind: ast::NamedField(ident, _), .. } => {
                        spans.push(field.span);
                        bools.push(token::get_ident(ident).get().to_string())
                    },
                    _ => {},
                }
            }
        }

        if bools.len() >= 3 {
            cx.span_lint(EXCESSIVE_BOOL_USAGE_STRUCTS, cx.tcx.map.span(id),
                format!("Struct contains an excessive number ({}) of bools ({}).  \
                    Did you want to create a state machine?",
                    bools.len(),
                    bools.connect(", ")).as_slice());
            for span in spans.iter() {
                cx.tcx.sess.span_note(*span, "boolean field defined here");
            }
        }
    }

    fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &ast::FnDecl,
            _: &ast::Block, sp: Span, _: ast::NodeId) {
        let mut spans = vec![];
        for arg in decl.inputs.iter() {
            if node_is_bool(cx, &*arg.ty) {
                spans.push(cx.tcx.map.span(arg.id));
            }
        }

        if spans.len() > 1 {
            cx.span_lint(EXCESSIVE_BOOL_USAGE_FUNCS, sp,
                format!("Funtion contains an excessive number ({}) of bools.  \
                    Perhaps you should use enumerated arguments?",
                    spans.len()).as_slice());
            for span in spans.iter() {
                cx.tcx.sess.span_note(*span, "boolean argument defined here");
            }
        }
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_lint_pass(box Pass as LintPassObject);
}
<commit_msg>Removed some deprecated functionality<commit_after>#![feature(macro_rules, plugin_registrar, quote, phase)]

#[phase(plugin, link)]
extern crate syntax;
#[phase(plugin, link)]
extern crate rustc;

use syntax::ast;
use rustc::lint::LintPassObject;
use rustc::plugin::Registry;
use rustc::lint::{Context, LintPass, LintArray};
use rustc::middle::def;
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::visit::FnKind;

declare_lint!(EXCESSIVE_BOOL_USAGE_STRUCTS, Warn,
              "Warn about exessive use of boolean members in structs.")
declare_lint!(EXCESSIVE_BOOL_USAGE_FUNCS, Warn,
              "Warn about exessive use of boolean arguments in functions.")

struct Pass;

fn node_is_bool(cx: &Context, ty: &ast::Ty) -> bool {
    match ty.node {
        ast::TyPath(_, _, id) => {
            match cx.tcx.def_map.borrow()[id].clone() {
                def::DefPrimTy(ast::TyBool) => true,
                _ => false,
            }
        },
        _ => false,
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(EXCESSIVE_BOOL_USAGE_STRUCTS, EXCESSIVE_BOOL_USAGE_FUNCS)
    }

    fn check_struct_def(&mut self, cx: &Context, def: &ast::StructDef,
            _: ast::Ident, _: &ast::Generics, id: ast::NodeId) {
        let mut bools = vec![];
        let mut spans = vec![];

        for field in def.fields.iter() {
            if node_is_bool(cx, &*field.node.ty) {
                match field.node {
                    ast::StructField_ { kind: ast::NamedField(ident, _), .. } => {
                        spans.push(field.span);
                        bools.push(token::get_ident(ident).get().to_string())
                    },
                    _ => {},
                }
            }
        }

        if bools.len() >= 3 {
            cx.span_lint(EXCESSIVE_BOOL_USAGE_STRUCTS, cx.tcx.map.span(id),
                format!("Struct contains an excessive number ({}) of bools ({}).  \
                    Did you want to create a state machine?",
                    bools.len(),
                    bools.connect(", ")).as_slice());
            for span in spans.iter() {
                cx.tcx.sess.span_note(*span, "boolean field defined here");
            }
        }
    }

    fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &ast::FnDecl,
            _: &ast::Block, sp: Span, _: ast::NodeId) {
        let mut spans = vec![];
        for arg in decl.inputs.iter() {
            if node_is_bool(cx, &*arg.ty) {
                spans.push(cx.tcx.map.span(arg.id));
            }
        }

        if spans.len() > 1 {
            cx.span_lint(EXCESSIVE_BOOL_USAGE_FUNCS, sp,
                format!("Funtion contains an excessive number ({}) of bools.  \
                    Perhaps you should use enumerated arguments?",
                    spans.len()).as_slice());
            for span in spans.iter() {
                cx.tcx.sess.span_note(*span, "boolean argument defined here");
            }
        }
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_lint_pass(box Pass as LintPassObject);
}
<|endoftext|>


<commit_before>//! Tool for making/verifying checksums of directory trees.
//!
//! # Library doc
//!
//! This library is used by `checksums` itself for all its function and is therefore contains all necessary functions.
//!
//! ## Data flow
//!
//! Hash verification
//!
//! ```plaintext
//! Options
//! |> create_hashes()
//! |> compare_hashes()
//! |> write_hash_comparison_results()
//! ```
//!
//! Hash creation
//!
//! ```plaintext
//! Options
//! |> write_hashes()
//! ```
//!
//! # Executable manpage
//!
//! ## SYNOPSIS
//!
//! [`checksums`](https://github.com/nabijaczleweli/checksums) [OPTIONS] [DIRECTORY]
//!
//! ## DESCRIPTION
//!
//! Tool for making/verifying checksums of directory trees.
//!
//! Use the generated checksums to automatically verify file/directory tree
//! correctness.
//!
//! ## OPTIONS
//!
//! -a --algorithm <algorithm>
//!
//! ```text
//! Set the hashing algorithm to use.
//!
//! Supported algorithms: SHA1, SHA2-256, SHA2-512, SHA3-256, SHA3-512, BLAKE,
//!                       BLAKE2, CRC8, CRC16, CRC32, CRC64, MD5, XOR8
//! ```
//!
//! -c --create
//!
//! ```text
//! Create directory hashes, rather than verifying them.
//!
//! Directory hashes are output to the output file, which, if not specified, will
//! be "`DIRECTORY`.hash".
//!
//! Will fail if the output file already exists and `--force` is not specified.
//!
//! Exclusive with `--verify`. Overrides `--verify`.
//! ```
//!
//! -v --verify
//!
//! ```text
//! Verify directory hashes. Default.
//!
//! Exclusive with `--create`. Overrides `--create`.
//! ```
//!
//! -d --depth <depth>
//!
//! ```text
//! Set max recursion depth to `depth`. Default: 0.
//!
//! Exclusive with `--recursive`. Overrides `--recursive`.
//! ```
//!
//! -r --recursive
//!
//! ```text
//! Set max recursion depth to infinity.
//!
//! Exclusive with `--depth`. Overrides `--depth`.
//! ```
//!
//! --follow-symlinks
//!
//! ```text
//! Recurse down symlinks. Default.
//! ```
//!
//! --no-follow-symlinks
//!
//! ```text
//! Don't recurse down symlinks.
//! ```
//!
//! -i --ignore <filename[,filename2][,filename3][,filenameN]...>...
//!
//! ```text
//! Add filename(s) to ignored files list. Default: none.
//!
//! Ignored files are marked as such.
//!
//! Accepted multiple times.
//! ```
//!
//! --force
//!
//! ```text
//! Override output file in `--create` mode. No meaning in `--verify` mode.
//! ```
//!
//! -j --jobs [jobs]
//!
//! ```text
//! Amount of threads used for hashing. Default: # of CPU threads
//!
//! One thread can hash one file at a time, potentially speeding up hashing up to `jobs` times.
//!
//! No/empty value: # of CPU threads. -1: Infinite
//! ```
//!
//! [DIRECTORY]
//!
//! ```text
//! Directory to create/verify hash for. Default: current workdir.
//! ```
//!
//! ## EXAMPLES
//!
//! `examples` [`-v`] [`-f` *infile*]
//!
//! ```text
//! Verify the current directory tree against the saved hashes.
//!
//! `-v` is not necessary as it's the default.
//!
//! *infile* defaults to "`DIRECTORY`.hash"
//! ```
//!
//! `examples` `-c` [`-f` *outfile*] [`--force`]
//!
//! ```text
//! Create hashes of the current directory tree for later verification.
//!
//! *outfile* defaults to "`DIRECTORY`.hash".
//!
//! Use `--force` to override *outfile*.
//! ```
//!
//! `examples` [`-d` *depth*] [`-r`] [`OTHER OPTIONS`]
//!
//! ```text
//! Recurse *depth* or infinity directories down.
//! ```

extern crate md5;
extern crate crc;
#[macro_use]
extern crate clap;
extern crate crc8;
extern crate crc16;
extern crate blake;
extern crate regex;
extern crate shaman;
extern crate futures;
extern crate num_cpus;
extern crate tabwriter;
extern crate blake2_rfc;
#[macro_use]
extern crate lazy_static;
extern crate tiny_keccak;
extern crate futures_cpupool;

mod hashing;
mod algorithms;

pub mod ops;
pub mod util;
pub mod options;

pub use hashing::*;
pub use algorithms::Algorithm;
<commit_msg>Fix top-level doc<commit_after>//! Tool for making/verifying checksums of directory trees.
//!
//! # Library doc
//!
//! This library is used by `checksums` itself for all its function and is therefore contains all necessary functions.
//!
//! ## Data flow
//!
//! Hash verification
//!
//! ```plaintext
//! Options
//! |> create_hashes()
//! |> compare_hashes()
//! |> write_hash_comparison_results()
//! ```
//!
//! Hash creation
//!
//! ```plaintext
//! Options
//! |> create_hashes()
//! |> write_hashes()
//! ```
//!
//! # Executable manpage
//!
//! ## SYNOPSIS
//!
//! [`checksums`](https://github.com/nabijaczleweli/checksums) [OPTIONS] [DIRECTORY]
//!
//! ## DESCRIPTION
//!
//! Tool for making/verifying checksums of directory trees.
//!
//! Use the generated checksums to automatically verify file/directory tree
//! correctness.
//!
//! ## OPTIONS
//!
//! -a --algorithm <algorithm>
//!
//! ```text
//! Set the hashing algorithm to use.
//!
//! Supported algorithms: SHA1, SHA2-256, SHA2-512, SHA3-256, SHA3-512, BLAKE,
//!                       BLAKE2, CRC8, CRC16, CRC32, CRC64, MD5, XOR8
//! ```
//!
//! -c --create
//!
//! ```text
//! Create directory hashes, rather than verifying them.
//!
//! Directory hashes are output to the output file, which, if not specified, will
//! be "`DIRECTORY`.hash".
//!
//! Will fail if the output file already exists and `--force` is not specified.
//!
//! Exclusive with `--verify`. Overrides `--verify`.
//! ```
//!
//! -v --verify
//!
//! ```text
//! Verify directory hashes. Default.
//!
//! Exclusive with `--create`. Overrides `--create`.
//! ```
//!
//! -d --depth <depth>
//!
//! ```text
//! Set max recursion depth to `depth`. Default: 0.
//!
//! Exclusive with `--recursive`. Overrides `--recursive`.
//! ```
//!
//! -r --recursive
//!
//! ```text
//! Set max recursion depth to infinity.
//!
//! Exclusive with `--depth`. Overrides `--depth`.
//! ```
//!
//! --follow-symlinks
//!
//! ```text
//! Recurse down symlinks. Default.
//! ```
//!
//! --no-follow-symlinks
//!
//! ```text
//! Don't recurse down symlinks.
//! ```
//!
//! -i --ignore <filename[,filename2][,filename3][,filenameN]...>...
//!
//! ```text
//! Add filename(s) to ignored files list. Default: none.
//!
//! Ignored files are marked as such.
//!
//! Accepted multiple times.
//! ```
//!
//! --force
//!
//! ```text
//! Override output file in `--create` mode. No meaning in `--verify` mode.
//! ```
//!
//! -j --jobs [jobs]
//!
//! ```text
//! Amount of threads used for hashing. Default: # of CPU threads
//!
//! One thread can hash one file at a time, potentially speeding up hashing up to `jobs` times.
//!
//! No/empty value: # of CPU threads. -1: Infinite
//! ```
//!
//! [DIRECTORY]
//!
//! ```text
//! Directory to create/verify hash for. Default: current workdir.
//! ```
//!
//! ## EXAMPLES
//!
//! `examples` [`-v`] [`-f` *infile*]
//!
//! ```text
//! Verify the current directory tree against the saved hashes.
//!
//! `-v` is not necessary as it's the default.
//!
//! *infile* defaults to "`DIRECTORY`.hash"
//! ```
//!
//! `examples` `-c` [`-f` *outfile*] [`--force`]
//!
//! ```text
//! Create hashes of the current directory tree for later verification.
//!
//! *outfile* defaults to "`DIRECTORY`.hash".
//!
//! Use `--force` to override *outfile*.
//! ```
//!
//! `examples` [`-d` *depth*] [`-r`] [`OTHER OPTIONS`]
//!
//! ```text
//! Recurse *depth* or infinity directories down.
//! ```

extern crate md5;
extern crate crc;
#[macro_use]
extern crate clap;
extern crate crc8;
extern crate crc16;
extern crate blake;
extern crate regex;
extern crate shaman;
extern crate futures;
extern crate num_cpus;
extern crate tabwriter;
extern crate blake2_rfc;
#[macro_use]
extern crate lazy_static;
extern crate tiny_keccak;
extern crate futures_cpupool;

mod hashing;
mod algorithms;

pub mod ops;
pub mod util;
pub mod options;

pub use hashing::*;
pub use algorithms::Algorithm;
<|endoftext|>


<commit_before>//! Look up OSTN02 adjustments for transforming ETRS89 Eastings and Northings
//! to OSGB36 Eastings and Northings
//!

const MIN_X_SHIFT: f64 = 86.275;
const MIN_Y_SHIFT: f64 = -81.603;
const MIN_Z_SHIFT: f64 = 43.982;

extern crate phf;
include!("ostn02.rs");

extern crate libc;
use libc::{c_double, uint32_t};

/// Return a 3-tuple of adjustments which convert ETRS89 Eastings and Northings
/// to OSGB36 Eastings, Northings, and Orthometric height
fn get_shifts(tup: (u32, u32)) -> (f64, f64, f64) {
    // look up the shifts, or return 9999.000
    let key = format!("{:03x}{:03x}", tup.1, tup.0);
    // some or None, so try! this
    match ostn02_lookup(&*key) {
        Some(res) => {
            (res.0 as f64 / 1000. + MIN_X_SHIFT,
             res.1 as f64 / 1000. + MIN_Y_SHIFT,
             res.2 as f64 / 1000. + MIN_Z_SHIFT)
        }
        None => (9999.000, 9999.000, 9999.000),
    }
}

#[repr(C)]
/// Incoming ETRS89 kilometer-grid references
pub struct GridRefs {
    pub easting: uint32_t,
    pub northing: uint32_t,
}

#[repr(C)]
#[derive(Debug)]
/// Outgoing OSTN02 Easting, Northing, and height adjustments
pub struct Adjustment {
    pub x_shift: c_double,
    pub y_shift: c_double,
    pub z_shift: c_double,
}

// From and Into traits for GridRefs
impl From<(u32, u32)> for GridRefs {
    fn from(gr: (u32, u32)) -> GridRefs {
        GridRefs {
            easting: gr.0,
            northing: gr.1,
        }
    }
}

impl From<GridRefs> for (u32, u32) {
    fn from(gr: GridRefs) -> (u32, u32) {
        (gr.easting, gr.northing)
    }
}

// From and Into traits for Adjustment
impl From<(f64, f64, f64)> for Adjustment {
    fn from(adj: (f64, f64, f64)) -> Adjustment {
        Adjustment {
            x_shift: adj.0,
            y_shift: adj.1,
            z_shift: adj.2,
        }
    }
}

impl From<Adjustment> for (f64, f64, f64) {
    fn from(adj: Adjustment) -> (f64, f64, f64) {
        (adj.x_shift, adj.y_shift, adj.z_shift)
    }
}

/// FFI function returning a 3-tuple of Easting, Northing, and height adjustments, for use in transforming
/// ETRS89 Eastings and Northings to OSGB36 Eastings, Northings.
/// The argument is a Struct containing kilometer-grid references of the ETRS89 Northings and Eastings you wish to convert
///
/// # Examples
///
/// ```python
/// # Python example using ctypes
/// import sys, ctypes
/// from ctypes import c_uint32, c_double, Structure
///
///
/// class GridRefs(Structure):
///     _fields_ = [("eastings", c_uint32),
///                 ("northings", c_uint32)]
///
///     def __str__(self):
///         return "({},{})".format(self.eastings, self.northings)
///
///
/// class Shifts(Structure):
///     _fields_ = [("x_shift", c_double),
///                 ("y_shift", c_double),
///                 ("z_shift", c_double)]
///
///     def __str__(self):
///         return "({}, {}, {})".format(self.x_shift, self.y_shift, self.z_shift)
///
///
/// prefix = {'win32': ''}.get(sys.platform, 'lib')
/// extension = {'darwin': '.dylib', 'win32': '.dll'}.get(sys.platform, '.so')
/// lib = ctypes.cdll.LoadLibrary(prefix + "ostn02_phf" + extension)
///
/// lib.get_shifts_ffi.argtypes = (GridRefs,)
/// lib.get_shifts_ffi.restype = Shifts
///
/// tup = GridRefs(651, 313)
///
/// # Should return (102.775, -78.244, 44.252)
/// print lib.get_shifts_ffi(tup)
/// ```
#[no_mangle]
pub extern "C" fn get_shifts_ffi(gr: GridRefs) -> Adjustment {
    get_shifts(gr.into()).into()
}

/// Return a 3-tuple of Easting, Northing, and height adjustments, for use in transforming
/// ETRS89 Eastings and Northings to OSGB36 Eastings, Northings.
/// The key is the combined hex-transformed (03x) kilometer-grid reference of the Northings and Eastings:
///
/// # Examples
///
/// ```
/// use ostn02_phf::ostn02_lookup;
///
/// // Caister Tower Eastings and Northings: 651307.003, 313255.686
/// let e_grid = (651307.003 / 1000.) as i32;
/// let n_grid = (313255.686 / 1000.) as i32;
/// let key = format!("{:03x}{:03x}", n_grid, e_grid);
/// // key is 13928b
/// let result = ostn02_lookup(&*key).unwrap();
/// // result should be (16500, 3359, 270)
/// assert_eq!(result, (16500, 3359, 270));
/// // remember that the actual adjustment for a coordinate is a bilinear transform, using a square
/// // see ostn02_shifts in https://github.com/urschrei/lonlat_bng/blob/master/src/ostn02/mod.rs
/// ```
pub fn ostn02_lookup(key: &str) -> Option<(i32, i32, i32)> {
    if key.is_empty() {
        return None;
    }
    OSTN02.get(&*key).cloned()
}

#[test]
fn test_internal_ffi() {
    assert_eq!((9999.000, 9999.000, 9999.000), get_shifts((615, 314)));
}

#[test]
fn test_ffi() {
    assert_eq!((9999.000, 9999.000, 9999.000), get_shifts_ffi((615, 314)));
}
<commit_msg>Add doc root<commit_after>#![doc(html_root_url = "https://urschrei.github.io/ostn02_phf/")]
//! Look up OSTN02 adjustments for transforming ETRS89 Eastings and Northings
//! to OSGB36 Eastings and Northings
//!

const MIN_X_SHIFT: f64 = 86.275;
const MIN_Y_SHIFT: f64 = -81.603;
const MIN_Z_SHIFT: f64 = 43.982;

extern crate phf;
include!("ostn02.rs");

extern crate libc;
use libc::{c_double, uint32_t};

/// Return a 3-tuple of adjustments which convert ETRS89 Eastings and Northings
/// to OSGB36 Eastings, Northings, and Orthometric height
fn get_shifts(tup: (u32, u32)) -> (f64, f64, f64) {
    // look up the shifts, or return 9999.000
    let key = format!("{:03x}{:03x}", tup.1, tup.0);
    // some or None, so try! this
    match ostn02_lookup(&*key) {
        Some(res) => {
            (res.0 as f64 / 1000. + MIN_X_SHIFT,
             res.1 as f64 / 1000. + MIN_Y_SHIFT,
             res.2 as f64 / 1000. + MIN_Z_SHIFT)
        }
        None => (9999.000, 9999.000, 9999.000),
    }
}

#[repr(C)]
/// Incoming ETRS89 kilometer-grid references
pub struct GridRefs {
    pub easting: uint32_t,
    pub northing: uint32_t,
}

#[repr(C)]
#[derive(Debug)]
/// Outgoing OSTN02 Easting, Northing, and height adjustments
pub struct Adjustment {
    pub x_shift: c_double,
    pub y_shift: c_double,
    pub z_shift: c_double,
}

// From and Into traits for GridRefs
impl From<(u32, u32)> for GridRefs {
    fn from(gr: (u32, u32)) -> GridRefs {
        GridRefs {
            easting: gr.0,
            northing: gr.1,
        }
    }
}

impl From<GridRefs> for (u32, u32) {
    fn from(gr: GridRefs) -> (u32, u32) {
        (gr.easting, gr.northing)
    }
}

// From and Into traits for Adjustment
impl From<(f64, f64, f64)> for Adjustment {
    fn from(adj: (f64, f64, f64)) -> Adjustment {
        Adjustment {
            x_shift: adj.0,
            y_shift: adj.1,
            z_shift: adj.2,
        }
    }
}

impl From<Adjustment> for (f64, f64, f64) {
    fn from(adj: Adjustment) -> (f64, f64, f64) {
        (adj.x_shift, adj.y_shift, adj.z_shift)
    }
}

/// FFI function returning a 3-tuple of Easting, Northing, and height adjustments, for use in transforming
/// ETRS89 Eastings and Northings to OSGB36 Eastings, Northings.
/// The argument is a Struct containing kilometer-grid references of the ETRS89 Northings and Eastings you wish to convert
///
/// # Examples
///
/// ```python
/// # Python example using ctypes
/// import sys, ctypes
/// from ctypes import c_uint32, c_double, Structure
///
///
/// class GridRefs(Structure):
///     _fields_ = [("eastings", c_uint32),
///                 ("northings", c_uint32)]
///
///     def __str__(self):
///         return "({},{})".format(self.eastings, self.northings)
///
///
/// class Shifts(Structure):
///     _fields_ = [("x_shift", c_double),
///                 ("y_shift", c_double),
///                 ("z_shift", c_double)]
///
///     def __str__(self):
///         return "({}, {}, {})".format(self.x_shift, self.y_shift, self.z_shift)
///
///
/// prefix = {'win32': ''}.get(sys.platform, 'lib')
/// extension = {'darwin': '.dylib', 'win32': '.dll'}.get(sys.platform, '.so')
/// lib = ctypes.cdll.LoadLibrary(prefix + "ostn02_phf" + extension)
///
/// lib.get_shifts_ffi.argtypes = (GridRefs,)
/// lib.get_shifts_ffi.restype = Shifts
///
/// tup = GridRefs(651, 313)
///
/// # Should return (102.775, -78.244, 44.252)
/// print lib.get_shifts_ffi(tup)
/// ```
#[no_mangle]
pub extern "C" fn get_shifts_ffi(gr: GridRefs) -> Adjustment {
    get_shifts(gr.into()).into()
}

/// Return a 3-tuple of Easting, Northing, and height adjustments, for use in transforming
/// ETRS89 Eastings and Northings to OSGB36 Eastings, Northings.
/// The key is the combined hex-transformed (03x) kilometer-grid reference of the Northings and Eastings:
///
/// # Examples
///
/// ```
/// use ostn02_phf::ostn02_lookup;
///
/// // Caister Tower Eastings and Northings: 651307.003, 313255.686
/// let e_grid = (651307.003 / 1000.) as i32;
/// let n_grid = (313255.686 / 1000.) as i32;
/// let key = format!("{:03x}{:03x}", n_grid, e_grid);
/// // key is 13928b
/// let result = ostn02_lookup(&*key).unwrap();
/// // result should be (16500, 3359, 270)
/// assert_eq!(result, (16500, 3359, 270));
/// // remember that the actual adjustment for a coordinate is a bilinear transform, using a square
/// // see ostn02_shifts in https://github.com/urschrei/lonlat_bng/blob/master/src/ostn02/mod.rs
/// ```
pub fn ostn02_lookup(key: &str) -> Option<(i32, i32, i32)> {
    if key.is_empty() {
        return None;
    }
    OSTN02.get(&*key).cloned()
}

#[test]
fn test_internal_ffi() {
    assert_eq!((9999.000, 9999.000, 9999.000), get_shifts((615, 314)));
}

#[test]
fn test_ffi() {
    assert_eq!((9999.000, 9999.000, 9999.000), get_shifts_ffi((615, 314)));
}
<|endoftext|>


<commit_before>//! A bit-set implementation for use in id-map. Notable differences from bit-set are the IntoIter
//! struct and retain() methods.

#![deny(missing_docs)]

#[cfg(test)]
mod tests;

use std::{fmt, slice, vec};
use std::iter::FromIterator;

/// The element type of the set.
pub type Id = usize;

/// The block type of the underlying representation.
pub type Block = u32;

/// The number of bits in the block type.
pub const BITS: usize = 32;

fn mask(bit: usize) -> Block {
    (1 as Block) << bit
}

/// Given n and k return the largest integer m such that m*k <= n
fn ceil_div(n: usize, k: usize) -> usize {
    if n % k == 0 { n / k } else { n / k + 1 }
}

/// A set of `usize` elements represented by a bit vector. blocks required is proportional to the
/// maximum element in the set.
pub struct IdSet {
    blocks: Vec<Block>,
    len: usize,
}

impl IdSet {
    #[inline]
    /// Creates an empty `IdSet`.
    pub fn new() -> Self {
        IdSet {
            blocks: Vec::new(),
            len: 0,
        }
    }

    #[inline]
    /// Creates a `IdSet` filled with all elements from 0 to n.
    pub fn new_filled(n: usize) -> Self {
        let (nwords, nbits) = (n / BITS, n % BITS);
        let mut blocks = vec![!0; nwords];
        if nbits != 0 {
            blocks.push(mask(nbits) - 1);
        }
        IdSet { blocks, len: n }
    }

    #[inline]
    /// Creates a empty `IdSet` that can hold elements up to n before reallocating.
    pub fn with_capacity(n: usize) -> Self {
        IdSet {
            blocks: Vec::with_capacity(ceil_div(n, BITS)),
            len: 0,
        }
    }

    #[inline]
    /// Creates a set from a raw set of bytes.
    pub fn from_bytes(bytes: &[Block]) -> Self {
        let blocks = Vec::from(bytes);
        let len = bytes
            .iter()
            .map(|&word| word.count_ones() as usize)
            .sum();
        IdSet { blocks, len }
    }

    #[inline]
    /// Returns the number of elements in the set.
    pub fn len(&self) -> usize {
        self.len
    }

    #[inline]
    /// Removes all elements from the set.
    pub fn clear(&mut self) {
        self.blocks.clear();
        self.len = 0;
    }

    #[inline]
    /// Inserts the given elements into the set, returning true if it was not already in the set.
    pub fn insert(&mut self, id: Id) -> bool {
        let (word, bit) = (id / BITS, id % BITS);
        let mask = mask(bit);

        if word < self.blocks.len() {
            if (self.blocks[word] & mask) == 0 {
                self.blocks[word] |= mask;
                self.len += 1;
                true
            } else {
                false
            }
        } else {
            self.blocks.resize(word + 1, 0);
            self.blocks[word] = mask;
            self.len += 1;
            true
        }
    }

    #[inline]
    /// Removes the given element from the set, returning true if it was in the set.
    pub fn remove(&mut self, id: Id) -> bool {
        let (word, bit) = (id / BITS, id % BITS);
        let mask = mask(bit);

        if word < self.blocks.len() {
            if (self.blocks[word] & mask) != 0 {
                self.blocks[word] &= !mask;
                self.len -= 1;
                true
            } else {
                false
            }
        } else {
            false
        }
    }

    #[inline]
    /// Returns true if the given element is in the set.
    pub fn contains(&self, id: Id) -> bool {
        let (word, bit) = (id / BITS, id % BITS);

        if word < self.blocks.len() {
            (self.blocks[word] & mask(bit)) != 0
        } else {
            false
        }
    }

    #[inline]
    /// Remove all elements that don't satisfy the predicate.
    pub fn retain<F: FnMut(Id) -> bool>(&mut self, mut pred: F) {
        let mut id = 0;
        for word in &mut self.blocks {
            for bit in 0..BITS {
                let mask = mask(bit);
                if (*word & mask) != 0 && !pred(id) {
                    self.len -= 1;
                    *word &= !mask;
                }
                id += 1;
            }
        }
    }

    #[inline]
    /// An iterator over all elements in increasing order.
    pub fn iter(&self) -> Iter {
        Iter {
            inner: self.blocks().into_id_iter(),
            len: self.len,
        }
    }

    #[inline]
    /// A consuming iterator over all elements in increasing order.
    pub fn into_iter(self) -> IntoIter {
        let len = self.len;
        IntoIter {
            inner: self.into_blocks().into_id_iter(),
            len,
        }
    }

    #[inline]
    /// An iterator over the blocks of the underlying representation.
    pub fn blocks(&self) -> Blocks {
        Blocks {
            inner: self.blocks.iter(),
        }
    }

    #[inline]
    /// A consuming iterator over the blocks of the underlying representation.
    pub fn into_blocks(self) -> IntoBlocks {
        IntoBlocks {
            inner: self.blocks.into_iter(),
        }
    }
}

impl Clone for IdSet {
    #[inline]
    fn clone(&self) -> Self {
        IdSet {
            blocks: self.blocks.clone(),
            len: self.len,
        }
    }

    #[inline]
    fn clone_from(&mut self, source: &Self) {
        self.blocks.clone_from(&source.blocks);
        self.len = source.len;
    }
}

impl fmt::Debug for IdSet {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{{")?;
        let mut iter = self.iter();
        if let Some(id) = iter.next() {
            write!(f, "{:?}", id)?;
            for id in iter {
                write!(f, ", {:?}", id)?;
            }
        }
        write!(f, "}}")
    }
}

impl Default for IdSet {
    #[inline]
    fn default() -> Self {
        IdSet::new()
    }
}

impl Eq for IdSet {}

impl PartialEq for IdSet {
    fn eq(&self, other: &Self) -> bool {
        if self.len != other.len {
            return false;
        }
        let (mut lhs, mut rhs) = (self.blocks.iter(), other.blocks.iter());
        loop {
            match (lhs.next(), rhs.next()) {
                (Some(&l), Some(&r)) => {
                    if l != r {
                        return false;
                    }
                }
                (None, None) => return true,
                (Some(&l), None) => return l == 0 && lhs.all(|&word| word == 0),
                (None, Some(&r)) => return r == 0 && rhs.all(|&word| word == 0),
            }
        }
    }
}

impl Extend<Id> for IdSet {
    #[inline]
    fn extend<I: IntoIterator<Item = Id>>(&mut self, iter: I) {
        for id in iter {
            self.insert(id);
        }
    }
}

impl FromIterator<Id> for IdSet {
    #[inline]
    fn from_iter<I: IntoIterator<Item = Id>>(iter: I) -> Self {
        let mut set = IdSet::new();
        for id in iter {
            set.insert(id);
        }
        set
    }
}

impl<'a> IntoIterator for &'a IdSet {
    type Item = Id;
    type IntoIter = Iter<'a>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

#[derive(Clone, Debug)]
/// An iterator over all elements in increasing order.
pub struct Iter<'a> {
    inner: IdIter<Blocks<'a>>,
    len: usize,
}

impl<'a> Iterator for Iter<'a> {
    type Item = Id;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        let id = self.inner.next();
        if id.is_some() {
            self.len -= 1;
        }
        id
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }
}

impl<'a> ExactSizeIterator for Iter<'a> {
    #[inline]
    fn len(&self) -> usize {
        self.len
    }
}

#[derive(Clone, Debug)]
/// A consuming iterator over all elements in increasing order.
pub struct IntoIter {
    inner: IdIter<IntoBlocks>,
    len: usize,
}

impl Iterator for IntoIter {
    type Item = Id;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {

        let id = self.inner.next();
        if id.is_some() {
            self.len -= 1;
        }
        id
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }
}

impl ExactSizeIterator for IntoIter {
    #[inline]
    fn len(&self) -> usize {
        self.len
    }
}

#[derive(Clone, Debug)]
/// Transforms an iterator over blocks into an iterator over elements.
pub struct IdIter<I> {
    blocks: I,
    word: Block,
    idx: usize,
}

impl<I> Iterator for IdIter<I> where I: ExactSizeIterator<Item = Block> {
    type Item = Id;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        while self.word == 0 {
            match self.blocks.next() {
                Some(word) => self.word = word,
                None => return None,
            }
            self.idx += BITS;
        }
        // remove the LSB of the current word
        let bit = (self.word & (!self.word + 1)) - 1;
        self.word &= self.word - 1;
        Some(self.idx + bit.count_ones() as usize)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let ones = self.word.count_ones() as usize;
        (ones, Some(self.blocks.len() * BITS + ones))
    }
}

/// An iterator over blocks of elements.
pub trait BlockIterator: ExactSizeIterator<Item = Block> + Sized {
    /// Creates an iterator over elements in the blocks.
    fn into_id_iter(mut self) -> IdIter<Self> {
        let word = self.next().unwrap_or(0);
        IdIter {
            blocks: self,
            word,
            idx: 0,
        }
    }
}

impl<I> BlockIterator for I where I: ExactSizeIterator<Item = Block> {}

#[derive(Clone, Debug)]
/// An iterator over the blocks of the underlying representation.
pub struct Blocks<'a> {
    inner: slice::Iter<'a, Block>,
}

impl<'a> Iterator for Blocks<'a> {
    type Item = Block;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next().map(|&block| block)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }
}

impl<'a> ExactSizeIterator for Blocks<'a> {
    fn len(&self) -> usize {
        self.inner.len()
    }
}

#[derive(Clone, Debug)]
/// A consuming iterator over the blocks of the underlying representation.
pub struct IntoBlocks {
    inner: vec::IntoIter<Block>,
}

impl Iterator for IntoBlocks {
    type Item = Block;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }
}

impl ExactSizeIterator for IntoBlocks {
    fn len(&self) -> usize {
        self.inner.len()
    }
}<commit_msg>add union, intersection and complement<commit_after>//! A bit-set implementation for use in id-map. Notable differences from bit-set are the IntoIter
//! struct and retain() methods.

#![deny(missing_docs)]

#[cfg(test)]
mod tests;

use std::{cmp, fmt, slice, vec};
use std::iter::FromIterator;

/// The element type of the set.
pub type Id = usize;

/// The block type of the underlying representation.
pub type Block = u32;

/// The number of bits in the block type.
pub const BITS: usize = 32;

fn mask(bit: usize) -> Block {
    (1 as Block) << bit
}

/// Given n and k return the largest integer m such that m*k <= n
fn ceil_div(n: usize, k: usize) -> usize {
    if n % k == 0 { n / k } else { n / k + 1 }
}

/// A set of `usize` elements represented by a bit vector. blocks required is proportional to the
/// maximum element in the set.
pub struct IdSet {
    blocks: Vec<Block>,
    len: usize,
}

impl IdSet {
    #[inline]
    /// Creates an empty `IdSet`.
    pub fn new() -> Self {
        IdSet {
            blocks: Vec::new(),
            len: 0,
        }
    }

    #[inline]
    /// Creates a `IdSet` filled with all elements from 0 to n.
    pub fn new_filled(n: usize) -> Self {
        let (nwords, nbits) = (n / BITS, n % BITS);
        let mut blocks = vec![!0; nwords];
        if nbits != 0 {
            blocks.push(mask(nbits) - 1);
        }
        IdSet { blocks, len: n }
    }

    #[inline]
    /// Creates a empty `IdSet` that can hold elements up to n before reallocating.
    pub fn with_capacity(n: usize) -> Self {
        IdSet {
            blocks: Vec::with_capacity(ceil_div(n, BITS)),
            len: 0,
        }
    }

    #[inline]
    /// Creates a set from a raw set of bytes.
    pub fn from_bytes(bytes: &[Block]) -> Self {
        let blocks = Vec::from(bytes);
        let len = bytes
            .iter()
            .map(|&word| word.count_ones() as usize)
            .sum();
        IdSet { blocks, len }
    }

    #[inline]
    /// Returns the number of elements in the set.
    pub fn len(&self) -> usize {
        self.len
    }

    #[inline]
    /// Removes all elements from the set.
    pub fn clear(&mut self) {
        self.blocks.clear();
        self.len = 0;
    }

    #[inline]
    /// Inserts the given elements into the set, returning true if it was not already in the set.
    pub fn insert(&mut self, id: Id) -> bool {
        let (word, bit) = (id / BITS, id % BITS);
        let mask = mask(bit);

        if word < self.blocks.len() {
            if (self.blocks[word] & mask) == 0 {
                self.blocks[word] |= mask;
                self.len += 1;
                true
            } else {
                false
            }
        } else {
            self.blocks.resize(word + 1, 0);
            self.blocks[word] = mask;
            self.len += 1;
            true
        }
    }

    #[inline]
    /// Removes the given element from the set, returning true if it was in the set.
    pub fn remove(&mut self, id: Id) -> bool {
        let (word, bit) = (id / BITS, id % BITS);
        let mask = mask(bit);

        if word < self.blocks.len() {
            if (self.blocks[word] & mask) != 0 {
                self.blocks[word] &= !mask;
                self.len -= 1;
                true
            } else {
                false
            }
        } else {
            false
        }
    }

    #[inline]
    /// Returns true if the given element is in the set.
    pub fn contains(&self, id: Id) -> bool {
        let (word, bit) = (id / BITS, id % BITS);

        if word < self.blocks.len() {
            (self.blocks[word] & mask(bit)) != 0
        } else {
            false
        }
    }

    #[inline]
    /// Remove all elements that don't satisfy the predicate.
    pub fn retain<F: FnMut(Id) -> bool>(&mut self, mut pred: F) {
        let mut id = 0;
        for word in &mut self.blocks {
            for bit in 0..BITS {
                let mask = mask(bit);
                if (*word & mask) != 0 && !pred(id) {
                    self.len -= 1;
                    *word &= !mask;
                }
                id += 1;
            }
        }
    }

    #[inline]
    /// An iterator over all elements in increasing order.
    pub fn iter(&self) -> Iter {
        Iter {
            inner: self.blocks().into_id_iter(),
            len: self.len,
        }
    }

    #[inline]
    /// A consuming iterator over all elements in increasing order.
    pub fn into_iter(self) -> IntoIter {
        let len = self.len;
        IntoIter {
            inner: self.into_blocks().into_id_iter(),
            len,
        }
    }

    #[inline]
    /// An iterator over the blocks of the underlying representation.
    pub fn blocks(&self) -> Blocks {
        Blocks { inner: self.blocks.iter() }
    }

    #[inline]
    /// A consuming iterator over the blocks of the underlying representation.
    pub fn into_blocks(self) -> IntoBlocks {
        IntoBlocks { inner: self.blocks.into_iter() }
    }

    #[inline]
    /// Iterator over the union of two sets.
    /// Equivalent to self.blocks().union(other.blocks()).into_id_iter().
    pub fn union<'a>(&'a self, other: &'a Self) -> IdIter<Union<Blocks<'a>, Blocks<'a>>> {
        self.blocks().union(other.blocks()).into_id_iter()
    }

    #[inline]
    /// Iterator over the intersection of two sets.
    /// Equivalent to self.blocks().intersection(other.blocks()).into_id_iter().
    pub fn intersection<'a>(&'a self,
                            other: &'a Self)
                            -> IdIter<Intersection<Blocks<'a>, Blocks<'a>>> {
        self.blocks()
            .intersection(other.blocks())
            .into_id_iter()
    }

    #[inline]
    /// Iterator over the complement of the set. This iterator will never return None.
    pub fn complement(&self) -> IdIter<Complement<Blocks>> {
        self.blocks().complement().into_id_iter()
    }
}

impl Clone for IdSet {
    #[inline]
    fn clone(&self) -> Self {
        IdSet {
            blocks: self.blocks.clone(),
            len: self.len,
        }
    }

    #[inline]
    fn clone_from(&mut self, source: &Self) {
        self.blocks.clone_from(&source.blocks);
        self.len = source.len;
    }
}

impl fmt::Debug for IdSet {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{{")?;
        let mut iter = self.iter();
        if let Some(id) = iter.next() {
            write!(f, "{:?}", id)?;
            for id in iter {
                write!(f, ", {:?}", id)?;
            }
        }
        write!(f, "}}")
    }
}

impl Default for IdSet {
    #[inline]
    fn default() -> Self {
        IdSet::new()
    }
}

impl Eq for IdSet {}

impl PartialEq for IdSet {
    fn eq(&self, other: &Self) -> bool {
        if self.len != other.len {
            return false;
        }
        let (mut lhs, mut rhs) = (self.blocks.iter(), other.blocks.iter());
        loop {
            match (lhs.next(), rhs.next()) {
                (Some(&l), Some(&r)) => {
                    if l != r {
                        return false;
                    }
                }
                (None, None) => return true,
                (Some(&l), None) => return l == 0 && lhs.all(|&word| word == 0),
                (None, Some(&r)) => return r == 0 && rhs.all(|&word| word == 0),
            }
        }
    }
}

impl Extend<Id> for IdSet {
    #[inline]
    fn extend<I: IntoIterator<Item = Id>>(&mut self, iter: I) {
        for id in iter {
            self.insert(id);
        }
    }
}

impl FromIterator<Id> for IdSet {
    #[inline]
    fn from_iter<I: IntoIterator<Item = Id>>(iter: I) -> Self {
        let mut set = IdSet::new();
        for id in iter {
            set.insert(id);
        }
        set
    }
}

impl<'a> IntoIterator for &'a IdSet {
    type Item = Id;
    type IntoIter = Iter<'a>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

#[derive(Clone, Debug)]
/// An iterator over all elements in increasing order.
pub struct Iter<'a> {
    inner: IdIter<Blocks<'a>>,
    len: usize,
}

impl<'a> Iterator for Iter<'a> {
    type Item = Id;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        let id = self.inner.next();
        if id.is_some() {
            self.len -= 1;
        }
        id
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }
}

impl<'a> ExactSizeIterator for Iter<'a> {
    #[inline]
    fn len(&self) -> usize {
        self.len
    }
}

#[derive(Clone, Debug)]
/// A consuming iterator over all elements in increasing order.
pub struct IntoIter {
    inner: IdIter<IntoBlocks>,
    len: usize,
}

impl Iterator for IntoIter {
    type Item = Id;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {

        let id = self.inner.next();
        if id.is_some() {
            self.len -= 1;
        }
        id
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }
}

impl ExactSizeIterator for IntoIter {
    #[inline]
    fn len(&self) -> usize {
        self.len
    }
}

#[derive(Clone, Debug)]
/// Transforms an iterator over blocks into an iterator over elements.
pub struct IdIter<B> {
    blocks: B,
    word: Block,
    idx: usize,
}

impl<B> Iterator for IdIter<B>
    where B: BlockIterator
{
    type Item = Id;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        while self.word == 0 {
            match self.blocks.next() {
                Some(word) => self.word = word,
                None => return None,
            }
            self.idx += BITS;
        }
        // remove the LSB of the current word
        let bit = (self.word & (!self.word + 1)) - 1;
        self.word &= self.word - 1;
        Some(self.idx + bit.count_ones() as usize)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let ones = self.word.count_ones() as usize;
        (ones, self.blocks.size_hint().1.map(|hi| hi * BITS + ones))
    }
}

/// An iterator over blocks of elements.
pub trait BlockIterator: Iterator<Item = Block> + Sized {
    /// Creates an iterator over elements in the blocks.
    fn into_id_iter(mut self) -> IdIter<Self> {
        let word = self.next().unwrap_or(0);
        IdIter {
            blocks: self,
            word,
            idx: 0,
        }
    }

    /// Take the union of two iterators.
    fn union<B: BlockIterator>(self, other: B) -> Union<Self, B> {
        Union {
            left: self,
            right: other,
        }
    }

    /// Take the intersection of two iterators.
    fn intersection<B: BlockIterator>(self, other: B) -> Intersection<Self, B> {
        Intersection {
            left: self,
            right: other,
        }
    }

    /// Take the complement of the iterator.
    fn complement(self) -> Complement<Self> {
        Complement { blocks: self }
    }
}

impl<I> BlockIterator for I where I: Iterator<Item = Block> {}

#[derive(Clone, Debug)]
/// An iterator over the blocks of the underlying representation.
pub struct Blocks<'a> {
    inner: slice::Iter<'a, Block>,
}

impl<'a> Iterator for Blocks<'a> {
    type Item = Block;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next().map(|&block| block)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }
}

impl<'a> ExactSizeIterator for Blocks<'a> {
    fn len(&self) -> usize {
        self.inner.len()
    }
}

#[derive(Clone, Debug)]
/// A consuming iterator over the blocks of the underlying representation.
pub struct IntoBlocks {
    inner: vec::IntoIter<Block>,
}

impl Iterator for IntoBlocks {
    type Item = Block;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }
}

impl ExactSizeIterator for IntoBlocks {
    fn len(&self) -> usize {
        self.inner.len()
    }
}

/// Takes the union of two block iterators.
pub struct Union<L, R> {
    left: L,
    right: R,
}

impl<L, R> Iterator for Union<L, R>
    where L: BlockIterator,
          R: BlockIterator
{
    type Item = Block;

    fn next(&mut self) -> Option<Self::Item> {
        match (self.left.next(), self.right.next()) {
            (Some(l), Some(r)) => Some(l | r),
            (Some(l), None) => Some(l),
            (None, Some(r)) => Some(r),
            (None, None) => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (llo, lhi) = self.left.size_hint();
        let (rlo, rhi) = self.right.size_hint();
        let lo = cmp::max(llo, rlo);
        let hi = if let (Some(lhi), Some(rhi)) = (lhi, rhi) {
            Some(cmp::max(lhi, rhi))
        } else {
            None
        };
        (lo, hi)
    }
}

impl<L, R> ExactSizeIterator for Union<L, R>
    where L: BlockIterator + ExactSizeIterator,
          R: BlockIterator + ExactSizeIterator
{
    fn len(&self) -> usize {
        cmp::max(self.left.len(), self.right.len())
    }
}

/// Takes the intersection of two block iterators.
pub struct Intersection<L, R> {
    left: L,
    right: R,
}

impl<L, R> Iterator for Intersection<L, R>
    where L: BlockIterator,
          R: BlockIterator
{
    type Item = Block;

    fn next(&mut self) -> Option<Self::Item> {
        if let (Some(l), Some(r)) = (self.left.next(), self.right.next()) {
            Some(l & r)
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (llo, lhi) = self.left.size_hint();
        let (rlo, rhi) = self.right.size_hint();
        let lo = cmp::max(llo, rlo);
        let hi = match (lhi, rhi) {
            (Some(lhi), Some(rhi)) => Some(cmp::min(lhi, rhi)),
            (Some(lhi), None) => Some(lhi),
            (None, Some(rhi)) => Some(rhi),
            (None, None) => None,
        };
        (lo, hi)
    }
}

impl<L, R> ExactSizeIterator for Intersection<L, R>
    where L: ExactSizeIterator<Item = Block>,
          R: ExactSizeIterator<Item = Block>
{
    fn len(&self) -> usize {
        cmp::max(self.left.len(), self.right.len())
    }
}

/// Takes the complement of a block iterator. This iterator will never return None.
pub struct Complement<B> {
    blocks: B,
}

impl<B> Iterator for Complement<B>
    where B: BlockIterator
{
    type Item = Block;

    fn next(&mut self) -> Option<Self::Item> {
        Some(!self.blocks.next().unwrap_or(0))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, None)
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate pretty_assertions;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

// we get an unused import when using macro use, but a
// "this has no effect without macro_use" message otherwise
#[allow(unused_imports)]
#[macro_use]
extern crate snapshot_proc_macro;

pub use snapshot_proc_macro::*;

use std::collections::BTreeMap;
use std::fmt::Debug;
use std::fs::{create_dir_all, File, OpenOptions};
use std::io::{BufReader, BufWriter};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use serde::Serialize;
use serde::de::DeserializeOwned;

type SnapFileContents = BTreeMap<String, Snapshot<serde_json::Value>>;

pub trait Snapable {}
impl<T> Snapable for T
where
    T: Debug + DeserializeOwned + Serialize,
{
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct Snapshot<S: Snapable> {
    pub file: String,
    pub module_path: String,
    pub test_function: String,
    pub recorded_value: S,
}

impl<S> Snapshot<S>
where
    S: Snapable + Debug + DeserializeOwned + PartialEq + Serialize,
{
    pub fn check_snapshot(&self, manifest_dir: &str) {
        let SnapFileSpec {
            absolute_path,
            relative_path,
            ..
        } = self.path(manifest_dir);

        let snap_file = match File::open(&absolute_path) {
            Ok(f) => f,
            Err(why) => {
                panic!(
                    "Unable to open snapshot file {:?}: {:?}",
                    relative_path,
                    why.kind()
                )
            }
        };

        let rdr = BufReader::new(snap_file);
        let mut module_snapshots: SnapFileContents = match serde_json::from_reader(rdr) {
            Ok(ps) => ps,
            Err(why) => {
                panic!("Unable to parse previous snapshot:\n{:#?}", why);
            }
        };

        let snap_key = self.module_key();
        let previous_snapshot = match module_snapshots.remove(&snap_key) {
            Some(s) => s,
            None => {
                panic!(
                    "Unable to find snapshot for test {:?} in {:?}",
                    snap_key,
                    relative_path
                )
            }
        };

        let Snapshot {
            recorded_value,
            file,
            module_path,
            test_function,
        } = previous_snapshot;

        match serde_json::from_value(recorded_value) {
            Ok(recorded_value) => {
                assert_eq!(
                    self.file,
                    file,
                    "Filename for snapshot test function doesn't match recorded one"
                );

                assert_eq!(
                    self.module_path,
                    module_path,
                    "Module paths for snapshot test function doesn't match recorded one"
                );

                assert_eq!(
                    self.test_function,
                    test_function,
                    "Test function name doesn't match recorded one"
                );

                assert_eq!(
                    self.recorded_value,
                    recorded_value,
                    "Test output doesn't match recorded snapshot!"
                );
            }
            Err(why) => {
                panic!(
                    "Unable to parse existing snapshot as correct type: {:?}",
                    why
                )
            }
        }
    }

    pub fn update_snapshot(&self, manifest_dir: &str) {
        let SnapFileSpec {
            dir: snap_dir,
            absolute_path,
            relative_path,
            ..
        } = self.path(manifest_dir);

        let mut dir_to_create = PathBuf::from(manifest_dir);
        dir_to_create.push(snap_dir.clone());
        match create_dir_all(&dir_to_create) {
            Ok(_) => (),
            Err(why) => {
                panic!(
                    "Unable to create snapshots directory {:?}: {:?}",
                    snap_dir,
                    why.kind()
                )
            }
        }

        let mut existing_snaps: SnapFileContents = match File::open(&absolute_path) {
            Ok(f) => {
                let mut rdr = BufReader::new(f);
                let mut contents = String::new();
                rdr.read_to_string(&mut contents)
                    .expect("Unable to read snapshot file we just opened.");

                match serde_json::from_str(&contents) {
                    Ok(v) => v,
                    Err(why) => {
                        panic!(
                            "Unable to parse potentially corrupt snapshot file {:?}: {:?}",
                            relative_path,
                            why
                        )
                    }
                }
            }
            Err(why) => {
                match why.kind() {
                    ::std::io::ErrorKind::NotFound => SnapFileContents::new(),
                    _ => {
                        panic!(
                            "Unable to open existing snapshot file {:?}: {:?}",
                            relative_path,
                            why.kind()
                        )
                    }
                }
            }

        };

        // now we need to update the particular snapshot we care about
        existing_snaps.insert(self.module_key(), self.create_deserializable());

        let writer = BufWriter::new(
            OpenOptions::new()
                .read(true)
                .write(true)
                .create(true)
                .open(&absolute_path)
                .expect("Unable to open/create file that we just opened/created!"),
        );

        match serde_json::to_writer_pretty(writer, &existing_snaps) {
            Ok(_) => (),
            Err(why) => {
                panic!(
                    "Unable to serialize or write snapshot result to {:?}: {:?}",
                    relative_path,
                    why
                )
            }
        }
    }

    fn module_key(&self) -> String {
        let mut snapshot_key = self.module_path.to_owned();
        snapshot_key.push_str("::");
        snapshot_key.push_str(&self.test_function);
        snapshot_key
    }

    fn create_deserializable(&self) -> Snapshot<serde_json::Value> {
        match serde_json::to_value(&self.recorded_value) {
            Ok(v) => {
                Snapshot {
                    file: self.file.clone(),
                    test_function: self.test_function.clone(),
                    module_path: self.module_path.clone(),
                    recorded_value: v,
                }
            }
            Err(why) => panic!("Unable to serialize test value: {:?}", why),
        }
    }

    fn path(&self, manifest_dir: &str) -> SnapFileSpec {
        let file_path = &Path::new(&self.file);

        let mut components = file_path.components();

        // strip the filename
        let mut filename = components.next_back().unwrap().as_os_str().to_owned();
        filename.push(".snap");

        let mut dir = PathBuf::new();
        for directory in components {
            dir.push(directory.as_os_str());
        }

        dir.push("__snapshots__");

        let mut absolute_path = PathBuf::from(manifest_dir);
        absolute_path.push(dir.clone());
        absolute_path.push(filename.clone());

        let mut relative_path = PathBuf::from(dir.clone());
        relative_path.push(filename.clone());

        SnapFileSpec {
            dir,
            absolute_path,
            relative_path,
        }
    }
}

struct SnapFileSpec {
    dir: PathBuf,
    relative_path: PathBuf,
    absolute_path: PathBuf,
}
<commit_msg>Make type alias public and more rustfmt thrash.<commit_after>#[macro_use]
extern crate pretty_assertions;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

// we get an unused import when using macro use, but a
// "this has no effect without macro_use" message otherwise
#[allow(unused_imports)]
#[macro_use]
extern crate snapshot_proc_macro;

pub use snapshot_proc_macro::*;

use std::collections::BTreeMap;
use std::fmt::Debug;
use std::fs::{create_dir_all, File, OpenOptions};
use std::io::{BufReader, BufWriter};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use serde::Serialize;
use serde::de::DeserializeOwned;

pub type SnapFileContents = BTreeMap<String, Snapshot<serde_json::Value>>;

pub trait Snapable {}
impl<T> Snapable for T where T: Debug + DeserializeOwned + Serialize {}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct Snapshot<S: Snapable> {
    pub file: String,
    pub module_path: String,
    pub test_function: String,
    pub recorded_value: S,
}

impl<S> Snapshot<S>
    where S: Snapable + Debug + DeserializeOwned + PartialEq + Serialize
{
    pub fn check_snapshot(&self, manifest_dir: &str) {
        let SnapFileSpec {
            absolute_path,
            relative_path,
            ..
        } = self.path(manifest_dir);

        let snap_file = match File::open(&absolute_path) {
            Ok(f) => f,
            Err(why) => {
                panic!("Unable to open snapshot file {:?}: {:?}",
                       relative_path,
                       why.kind())
            }
        };

        let rdr = BufReader::new(snap_file);
        let mut module_snapshots: SnapFileContents = match serde_json::from_reader(rdr) {
            Ok(ps) => ps,
            Err(why) => {
                panic!("Unable to parse previous snapshot:\n{:#?}", why);
            }
        };

        let snap_key = self.module_key();
        let previous_snapshot = match module_snapshots.remove(&snap_key) {
            Some(s) => s,
            None => {
                panic!("Unable to find snapshot for test {:?} in {:?}",
                       snap_key,
                       relative_path)
            }
        };

        let Snapshot {
            recorded_value,
            file,
            module_path,
            test_function,
        } = previous_snapshot;

        match serde_json::from_value(recorded_value) {
            Ok(recorded_value) => {
                assert_eq!(self.file,
                           file,
                           "Filename for snapshot test function doesn't match recorded one");

                assert_eq!(self.module_path,
                           module_path,
                           "Module paths for snapshot test function doesn't match recorded one");

                assert_eq!(self.test_function,
                           test_function,
                           "Test function name doesn't match recorded one");

                assert_eq!(self.recorded_value,
                           recorded_value,
                           "Test output doesn't match recorded snapshot!");
            }
            Err(why) => {
                panic!("Unable to parse existing snapshot as correct type: {:?}",
                       why)
            }
        }
    }

    pub fn update_snapshot(&self, manifest_dir: &str) {
        let SnapFileSpec {
            dir: snap_dir,
            absolute_path,
            relative_path,
            ..
        } = self.path(manifest_dir);

        let mut dir_to_create = PathBuf::from(manifest_dir);
        dir_to_create.push(snap_dir.clone());
        match create_dir_all(&dir_to_create) {
            Ok(_) => (),
            Err(why) => {
                panic!("Unable to create snapshots directory {:?}: {:?}",
                       snap_dir,
                       why.kind())
            }
        }

        let mut existing_snaps: SnapFileContents = match File::open(&absolute_path) {
            Ok(f) => {
                let mut rdr = BufReader::new(f);
                let mut contents = String::new();
                rdr.read_to_string(&mut contents)
                    .expect("Unable to read snapshot file we just opened.");

                match serde_json::from_str(&contents) {
                    Ok(v) => v,
                    Err(why) => {
                        panic!("Unable to parse potentially corrupt snapshot file {:?}: {:?}",
                               relative_path,
                               why)
                    }
                }
            }
            Err(why) => {
                match why.kind() {
                    ::std::io::ErrorKind::NotFound => SnapFileContents::new(),
                    _ => {
                        panic!("Unable to open existing snapshot file {:?}: {:?}",
                               relative_path,
                               why.kind())
                    }
                }
            }

        };

        // now we need to update the particular snapshot we care about
        existing_snaps.insert(self.module_key(), self.create_deserializable());

        let writer =
            BufWriter::new(OpenOptions::new()
                               .read(true)
                               .write(true)
                               .create(true)
                               .open(&absolute_path)
                               .expect("Unable to open/create file that we just opened/created!",));

        match serde_json::to_writer_pretty(writer, &existing_snaps) {
            Ok(_) => (),
            Err(why) => {
                panic!("Unable to serialize or write snapshot result to {:?}: {:?}",
                       relative_path,
                       why)
            }
        }
    }

    fn module_key(&self) -> String {
        let mut snapshot_key = self.module_path.to_owned();
        snapshot_key.push_str("::");
        snapshot_key.push_str(&self.test_function);
        snapshot_key
    }

    fn create_deserializable(&self) -> Snapshot<serde_json::Value> {
        match serde_json::to_value(&self.recorded_value) {
            Ok(v) => {
                Snapshot {
                    file: self.file.clone(),
                    test_function: self.test_function.clone(),
                    module_path: self.module_path.clone(),
                    recorded_value: v,
                }
            }
            Err(why) => panic!("Unable to serialize test value: {:?}", why),
        }
    }

    fn path(&self, manifest_dir: &str) -> SnapFileSpec {
        let file_path = &Path::new(&self.file);

        let mut components = file_path.components();

        // strip the filename
        let mut filename = components.next_back().unwrap().as_os_str().to_owned();
        filename.push(".snap");

        let mut dir = PathBuf::new();
        for directory in components {
            dir.push(directory.as_os_str());
        }

        dir.push("__snapshots__");

        let mut absolute_path = PathBuf::from(manifest_dir);
        absolute_path.push(dir.clone());
        absolute_path.push(filename.clone());

        let mut relative_path = PathBuf::from(dir.clone());
        relative_path.push(filename.clone());

        SnapFileSpec {
            dir,
            absolute_path,
            relative_path,
        }
    }
}

struct SnapFileSpec {
    dir: PathBuf,
    relative_path: PathBuf,
    absolute_path: PathBuf,
}
<|endoftext|>


<commit_before>#![allow(unstable)]
extern crate num;

use num::{Complex, Zero};
use std::iter::{repeat, range_step_inclusive, range_step};
use std::f32;

pub struct FFT {
    scratch: Vec<Complex<f32>>,
    factors: Vec<(usize, usize)>,
    twiddles: Vec<Complex<f32>>,
}

impl FFT {
    pub fn new(len: usize) -> Self {
        FFT {
            scratch: repeat(Zero::zero()).take(len).collect(),
            factors: factor(len),
            twiddles: range(0, len)
                      .map(|i| -1. * (i as f32) * f32::consts::PI_2 / (len as f32))
                      .map(|phase| Complex::from_polar(&1., &phase))
                      .collect(),
        }
    }

    pub fn process(&mut self, signal: &[Complex<f32>], spectrum: &mut [Complex<f32>]) {
        cooley_tukey(signal, 1,
                     spectrum, 1,
                     self.scratch.as_mut_slice(), 1,
                     self.twiddles.as_slice(),
                     self.factors.as_slice());
    }
}

//TODO can we collapse all these strides into one stride value?
fn cooley_tukey(signal: &[Complex<f32>],
                signal_stride: usize,
                spectrum: &mut [Complex<f32>],
                spectrum_stride: usize,
                scratch: &mut [Complex<f32>],
                scratch_stride: usize,
                twiddles: &[Complex<f32>],
                factors: &[(usize, usize)]) {
    match factors {
        [_] | [] => dft_slice(signal, signal_stride,
                              spectrum, spectrum_stride,
                              twiddles),
        [(n1, n2), other_factors..] => {
            for i in range(0, n1)
            {
                // perform the smaller FFTs from the signal buffer into
                // the scratch buffer, using the spectrum buffer as scratch space
                cooley_tukey(signal.slice_from(i * signal_stride), signal_stride * n1,
                             scratch.slice_from_mut(i * scratch_stride), scratch_stride * n1,
                             spectrum.slice_from_mut(i * spectrum_stride), spectrum_stride * n1,
                             twiddles, other_factors);
            }

            butterfly(scratch, scratch_stride,
                      spectrum, spectrum_stride,
                      twiddles, n1, n2);
        }
    }
}

fn butterfly(input: &[Complex<f32>],
             input_stride: usize,
             output: &mut [Complex<f32>],
             output_stride: usize,
             twiddles: &[Complex<f32>],
             num_cols: usize,
             num_rows: usize) {
    // for each row in input
    for (i, in_row) in input.chunks(num_cols * input_stride).enumerate() {
        let out_col = output.slice_from_mut(i * output_stride);
        let out_col_stride = output_stride * num_rows;
        for (j, spec_bin_idx) in range_step(0, out_col.len(), out_col_stride).enumerate() {
            let spec_bin = unsafe { out_col.get_unchecked_mut(spec_bin_idx) };
            *spec_bin = Zero::zero();
            let mut twiddle_idx = 0;
            for (k, sig_bin_idx) in range_step(0, in_row.len(), input_stride).enumerate() {
                let sig_bin = unsafe { in_row.get_unchecked(sig_bin_idx) };
                let twiddle = unsafe {
                    twiddles.get_unchecked(twiddle_idx)
                };
                *spec_bin = *spec_bin + *twiddle * *sig_bin;
                //SPEED change multiplications to repeated sums
                twiddle_idx += (i + j * num_rows) * input_stride;
                if twiddle_idx > twiddles.len() { twiddle_idx -= twiddles.len() }
            }
        }
    }
}

pub fn dft_slice(signal: &[Complex<f32>],
                 signal_stride: usize,
                 spectrum: &mut [Complex<f32>],
                 spectrum_stride: usize,
                 twiddles: &[Complex<f32>]) {
    let mut twiddle_idx_increase = 0;
    for spec_bin_idx in range_step(0, spectrum.len(), spectrum_stride) {
        let spec_bin = unsafe { spectrum.get_unchecked_mut(spec_bin_idx) };
        *spec_bin = Zero::zero();
        let mut twiddle_idx = 0;
        for signal_bin_idx in range_step(0, signal.len(), signal_stride) {
            let signal_bin = unsafe { signal.get_unchecked(signal_bin_idx) };
            let twiddle = unsafe { twiddles.get_unchecked(twiddle_idx) };
            *spec_bin = *spec_bin + twiddle * *signal_bin;
            twiddle_idx += twiddle_idx_increase;
            if twiddle_idx > twiddles.len() {twiddle_idx -= twiddles.len()}
        }
        twiddle_idx_increase += signal_stride;
    }
}

pub fn dft<'a, 'b, I, O>(signal: I, spectrum: O)
where I: Iterator<Item=&'a Complex<f32>> + ExactSizeIterator + Clone,
      O: Iterator<Item=&'b mut Complex<f32>>
{
    for (k, spec_bin) in spectrum.enumerate()
    {
        let signal_iter = signal.clone();
        let mut sum: Complex<f32> = Zero::zero();
        for (i, &x) in signal_iter.enumerate() {
            let angle = -1. * ((i * k) as f32) * f32::consts::PI_2 / (signal.len() as f32);
            let twiddle: Complex<f32> = Complex::from_polar(&1f32, &angle);
            sum = sum + twiddle * x;
        }
        *spec_bin = sum;
    }
}

fn factor(n: usize) -> Vec<(usize, usize)>
{
    let mut factors = Vec::new();
    let mut next = n;
    while next > 1
    {
        for div in Some(2us).into_iter().chain(range_step_inclusive(3us, next, 2))
        {
            if next % div == 0
            {
                next = next / div;
                factors.push((div, next));
                break;
            }
        }
    }
    return factors;
}
<commit_msg>More speed improvements with twiddle idx incrementing<commit_after>#![allow(unstable)]
extern crate num;

use num::{Complex, Zero};
use std::iter::{repeat, range_step_inclusive, range_step};
use std::f32;

pub struct FFT {
    scratch: Vec<Complex<f32>>,
    factors: Vec<(usize, usize)>,
    twiddles: Vec<Complex<f32>>,
}

impl FFT {
    pub fn new(len: usize) -> Self {
        FFT {
            scratch: repeat(Zero::zero()).take(len).collect(),
            factors: factor(len),
            twiddles: range(0, len)
                      .map(|i| -1. * (i as f32) * f32::consts::PI_2 / (len as f32))
                      .map(|phase| Complex::from_polar(&1., &phase))
                      .collect(),
        }
    }

    pub fn process(&mut self, signal: &[Complex<f32>], spectrum: &mut [Complex<f32>]) {
        cooley_tukey(signal, 1,
                     spectrum, 1,
                     self.scratch.as_mut_slice(), 1,
                     self.twiddles.as_slice(),
                     self.factors.as_slice());
    }
}

//TODO can we collapse all these strides into one stride value?
fn cooley_tukey(signal: &[Complex<f32>],
                signal_stride: usize,
                spectrum: &mut [Complex<f32>],
                spectrum_stride: usize,
                scratch: &mut [Complex<f32>],
                scratch_stride: usize,
                twiddles: &[Complex<f32>],
                factors: &[(usize, usize)]) {
    match factors {
        [_] | [] => dft_slice(signal, signal_stride,
                              spectrum, spectrum_stride,
                              twiddles),
        [(n1, n2), other_factors..] => {
            for i in range(0, n1)
            {
                // perform the smaller FFTs from the signal buffer into
                // the scratch buffer, using the spectrum buffer as scratch space
                cooley_tukey(signal.slice_from(i * signal_stride), signal_stride * n1,
                             scratch.slice_from_mut(i * scratch_stride), scratch_stride * n1,
                             spectrum.slice_from_mut(i * spectrum_stride), spectrum_stride * n1,
                             twiddles, other_factors);
            }

            butterfly(scratch, scratch_stride,
                      spectrum, spectrum_stride,
                      twiddles, n1, n2);
        }
    }
}

fn butterfly(input: &[Complex<f32>],
             input_stride: usize,
             output: &mut [Complex<f32>],
             output_stride: usize,
             twiddles: &[Complex<f32>],
             num_cols: usize,
             num_rows: usize) {
    // for each row in input
    let mut twiddle_idx_increase_1 = 0;
    for (i, in_row) in input.chunks(num_cols * input_stride).enumerate() {
        let out_col = output.slice_from_mut(i * output_stride);
        let out_col_stride = output_stride * num_rows;
        let mut twiddle_idx_increase_2 = 0;
        for spec_bin_idx in range_step(0, out_col.len(), out_col_stride) {
            let spec_bin = unsafe { out_col.get_unchecked_mut(spec_bin_idx) };
            *spec_bin = Zero::zero();
            let mut twiddle_idx = 0;
            let twiddle_idx_increase = twiddle_idx_increase_1 + twiddle_idx_increase_2;
            for sig_bin_idx in range_step(0, in_row.len(), input_stride) {
                let sig_bin = unsafe { in_row.get_unchecked(sig_bin_idx) };
                let twiddle = unsafe {
                    twiddles.get_unchecked(twiddle_idx)
                };
                *spec_bin = *spec_bin + *twiddle * *sig_bin;
                twiddle_idx += twiddle_idx_increase;
                if twiddle_idx > twiddles.len() { twiddle_idx -= twiddles.len() }
            }
            twiddle_idx_increase_2 += num_rows * input_stride;
        }
        twiddle_idx_increase_1 += input_stride;
    }
}

pub fn dft_slice(signal: &[Complex<f32>],
                 signal_stride: usize,
                 spectrum: &mut [Complex<f32>],
                 spectrum_stride: usize,
                 twiddles: &[Complex<f32>]) {
    let mut twiddle_idx_increase = 0;
    for spec_bin_idx in range_step(0, spectrum.len(), spectrum_stride) {
        let spec_bin = unsafe { spectrum.get_unchecked_mut(spec_bin_idx) };
        *spec_bin = Zero::zero();
        let mut twiddle_idx = 0;
        for signal_bin_idx in range_step(0, signal.len(), signal_stride) {
            let signal_bin = unsafe { signal.get_unchecked(signal_bin_idx) };
            let twiddle = unsafe { twiddles.get_unchecked(twiddle_idx) };
            *spec_bin = *spec_bin + twiddle * *signal_bin;
            twiddle_idx += twiddle_idx_increase;
            if twiddle_idx > twiddles.len() {twiddle_idx -= twiddles.len()}
        }
        twiddle_idx_increase += signal_stride;
    }
}

pub fn dft<'a, 'b, I, O>(signal: I, spectrum: O)
where I: Iterator<Item=&'a Complex<f32>> + ExactSizeIterator + Clone,
      O: Iterator<Item=&'b mut Complex<f32>>
{
    for (k, spec_bin) in spectrum.enumerate()
    {
        let signal_iter = signal.clone();
        let mut sum: Complex<f32> = Zero::zero();
        for (i, &x) in signal_iter.enumerate() {
            let angle = -1. * ((i * k) as f32) * f32::consts::PI_2 / (signal.len() as f32);
            let twiddle: Complex<f32> = Complex::from_polar(&1f32, &angle);
            sum = sum + twiddle * x;
        }
        *spec_bin = sum;
    }
}

fn factor(n: usize) -> Vec<(usize, usize)>
{
    let mut factors = Vec::new();
    let mut next = n;
    while next > 1
    {
        for div in Some(2us).into_iter().chain(range_step_inclusive(3us, next, 2))
        {
            if next % div == 0
            {
                next = next / div;
                factors.push((div, next));
                break;
            }
        }
    }
    return factors;
}
<|endoftext|>


<commit_before>//! # `attaca` - distributed, resilient version control with a git-like interface

#![feature(proc_macro, conservative_impl_trait, generators, offset_to)]
#![recursion_limit="128"]

#[cfg(test)]
#[macro_use]
extern crate quickcheck;

extern crate bincode;
extern crate chrono;
extern crate digest_writer;
#[macro_use]
extern crate error_chain;
extern crate futures_await as futures;
extern crate futures_bufio;
extern crate futures_cpupool;
extern crate generic_array;
extern crate itertools;
#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate memmap;
extern crate owning_ref;
extern crate qp_trie;
extern crate rad;
extern crate stable_deref_trait;
#[macro_use]
extern crate serde_derive;
extern crate seahash;
extern crate sha3;
extern crate toml;
extern crate typenum;

pub mod arc_slice;
pub mod batch;
pub mod catalog;
pub mod context;
pub mod errors;
pub mod index;
pub mod local;
pub mod marshal;
pub mod remote;
pub mod repository;
pub mod split;
pub mod trace;

pub use errors::{Error, ErrorKind, Result};

use std::path::{Path, PathBuf};

/// Controls the size of the MPSC queue between marshal tasks and write tasks.
const BATCH_FUTURE_BUFFER_SIZE: usize = 64;

/// Controls the size of buffers over buffered streams created when writing to remotes.
const WRITE_FUTURE_BUFFER_SIZE: usize = 64;

lazy_static! {
    /// Controls the name of the "hidden" `.attaca` repository metadata directory.
    static ref METADATA_PATH: &'static Path = Path::new(".attaca");

    /// The relative path of the repository config file.
    static ref CONFIG_PATH: PathBuf = METADATA_PATH.join("config.toml");

    /// The relative path of the blob directory within a repository.
    static ref BLOBS_PATH: PathBuf = METADATA_PATH.join("blobs");

    /// The relative path of the remote catalog directory.
    static ref REMOTE_CATALOGS_PATH: PathBuf = METADATA_PATH.join("remote-catalogs");

    /// The location of the local catalog file.
    static ref LOCAL_CATALOG_PATH: PathBuf = METADATA_PATH.join("local.catalog");

    /// The location of the index file.
    static ref INDEX_PATH: PathBuf = METADATA_PATH.join("index.bin");
}
<commit_msg>Fail compilation on 32-bit systems, fixes #8<commit_after>//! # `attaca` - distributed, resilient version control with a git-like interface

#![feature(proc_macro, conservative_impl_trait, generators, offset_to)]
#![recursion_limit="128"]

#[cfg(not(target_pointer_width = "64"))]
compile_error!(
    "Must be compiled on a 64-bit architecture due to the use of memory-mapping for potentially extremely large files!"
);

#[cfg(test)]
#[macro_use]
extern crate quickcheck;

extern crate bincode;
extern crate chrono;
extern crate digest_writer;
#[macro_use]
extern crate error_chain;
extern crate futures_await as futures;
extern crate futures_bufio;
extern crate futures_cpupool;
extern crate generic_array;
extern crate itertools;
#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate memmap;
extern crate owning_ref;
extern crate qp_trie;
extern crate rad;
extern crate stable_deref_trait;
#[macro_use]
extern crate serde_derive;
extern crate seahash;
extern crate sha3;
extern crate toml;
extern crate typenum;

pub mod arc_slice;
pub mod batch;
pub mod catalog;
pub mod context;
pub mod errors;
pub mod index;
pub mod local;
pub mod marshal;
pub mod remote;
pub mod repository;
pub mod split;
pub mod trace;

pub use errors::{Error, ErrorKind, Result};

use std::path::{Path, PathBuf};

/// Controls the size of the MPSC queue between marshal tasks and write tasks.
const BATCH_FUTURE_BUFFER_SIZE: usize = 64;

/// Controls the size of buffers over buffered streams created when writing to remotes.
const WRITE_FUTURE_BUFFER_SIZE: usize = 64;

lazy_static! {
    /// Controls the name of the "hidden" `.attaca` repository metadata directory.
    static ref METADATA_PATH: &'static Path = Path::new(".attaca");

    /// The relative path of the repository config file.
    static ref CONFIG_PATH: PathBuf = METADATA_PATH.join("config.toml");

    /// The relative path of the blob directory within a repository.
    static ref BLOBS_PATH: PathBuf = METADATA_PATH.join("blobs");

    /// The relative path of the remote catalog directory.
    static ref REMOTE_CATALOGS_PATH: PathBuf = METADATA_PATH.join("remote-catalogs");

    /// The location of the local catalog file.
    static ref LOCAL_CATALOG_PATH: PathBuf = METADATA_PATH.join("local.catalog");

    /// The location of the index file.
    static ref INDEX_PATH: PathBuf = METADATA_PATH.join("index.bin");
}
<|endoftext|>