<commit_before>#![feature(try_trait)]

extern crate pgn_reader;
extern crate memmap;
extern crate madvise;
extern crate btoi;
extern crate rand;
extern crate reqwest;

use std::env;
use std::mem;
use std::cmp::min;
use std::fs::File;
use std::option::NoneError;
use std::io::Read;

use memmap::Mmap;
use madvise::{AccessPattern, AdviseMemory};
use pgn_reader::{Visitor, Skip, Reader, San};
use btoi::ParseIntegerError;
use rand::{random, Closed01};

const BATCH_SIZE: usize = 50;

const MAX_PLIES: usize = 50;

#[derive(Debug)]
enum TimeControl {
    UltraBullet,
    Bullet,
    Blitz,
    Rapid,
    Classical,
    Correspondence,
}

#[derive(Debug)]
struct TimeControlError;

impl From<NoneError> for TimeControlError {
    fn from(_: NoneError) -> TimeControlError {
        TimeControlError { }
    }
}

impl From<ParseIntegerError> for TimeControlError {
    fn from(_: ParseIntegerError) -> TimeControlError {
        TimeControlError { }
    }
}

impl TimeControl {
    fn from_seconds_and_increment(seconds: u64, increment: u64) -> TimeControl {
        let total = seconds + 40 * increment;

        if total < 30 {
            TimeControl::UltraBullet
        } else if total < 180 {
            TimeControl::Bullet
        } else if total < 480 {
            TimeControl::Blitz
        } else if total < 1500 {
            TimeControl::Rapid
        } else if total < 21600 {
            TimeControl::Classical
        } else {
            TimeControl::Correspondence
        }
    }

    fn from_bytes(bytes: &[u8]) -> Result<TimeControl, TimeControlError> {
        if bytes == b"-" {
            return Ok(TimeControl::Correspondence);
        }

        let mut parts = bytes.splitn(2, |ch| *ch == b'+');
        let seconds = btoi::btou(parts.next()?)?;
        let increment = btoi::btou(parts.next()?)?;
        Ok(TimeControl::from_seconds_and_increment(seconds, increment))
    }
}

struct Indexer {
    context: String,

    white_elo: i16,
    black_elo: i16,
    time_control: TimeControl,
    skip: bool,

    current_game: Vec<u8>,
    plies: usize,
    standard: bool,

    batch: Vec<u8>,
    batch_size: usize,
}

impl Indexer {
    fn new(context: &str) -> Indexer {
        Indexer {
            context: context.into(),

            white_elo: 0,
            black_elo: 0,
            time_control: TimeControl::Correspondence,
            skip: true,

            current_game: Vec::new(),
            plies: 0,
            standard: true,

            batch: Vec::new(),
            batch_size: 0,
        }
    }

    fn send(&mut self) {
        if self.batch_size > 0 {
            self.batch_size = 0;

            let mut res = reqwest::Client::new()
                .put("http://localhost:9000/import/lichess")
                .body(mem::replace(&mut self.batch, Vec::new()))
                .send().expect("send batch");

            let mut answer = String::new();
            res.read_to_string(&mut answer).expect("decode response");
            println!("{}: {}", self.context, answer);
            assert!(res.status().is_success());
        }
    }
}

impl<'pgn> Visitor<'pgn> for Indexer {
    type Result = ();

    fn begin_game(&mut self) {
        self.current_game.clear();
        self.plies = 0;
    }

    fn begin_headers(&mut self) {
        self.white_elo = 0;
        self.black_elo = 0;
        self.time_control = TimeControl::Correspondence;
        self.standard = true;
    }

    fn header(&mut self, key: &'pgn [u8], value: &'pgn [u8]) {
        if key == b"WhiteElo" {
            self.white_elo = if value == b"?" { 0 } else { btoi::btoi(value).expect("WhiteElo") };
        } else if key == b"BlackElo" {
            self.black_elo = if value == b"?" { 0 } else { btoi::btoi(value).expect("BlackElo") };
        } else if key == b"TimeControl" {
            self.time_control = TimeControl::from_bytes(value).expect("TimeControl");
        } else if key == b"Variant" {
            self.standard = value == b"Standard";
            if self.standard {
                return; // we add this unconditionally later
            }
        }

        let (key, value) = if key == b"Site" {
            (&b"LichessID"[..], value.rsplitn(2, |ch| *ch == b'/').next().expect("Site"))
        } else {
            (key, value)
        };

        self.current_game.push(b'[');
        self.current_game.extend(key);
        self.current_game.extend(b" \"");
        self.current_game.extend(value);
        self.current_game.extend(b"\"]\n");
    }

    fn end_headers(&mut self) -> Skip {
        let rating = (self.white_elo + self.black_elo) / 2;

        let probability = if self.standard {
            self.current_game.extend(b"[Variant \"Standard\"]\n");

            match self.time_control {
                TimeControl::Correspondence | TimeControl::Classical => 1.0,
                TimeControl::Rapid if rating >= 2000 => 1.0,
                TimeControl::Rapid if rating >= 1800 => 2.0 / 5.0,
                TimeControl::Rapid => 1.0 / 8.0,
                TimeControl::Blitz if rating >= 2000 => 1.0,
                TimeControl::Blitz if rating >= 1800 => 1.0 / 4.0,
                TimeControl::Blitz => 1.0 / 15.0,
                TimeControl::Bullet if rating >= 2300 => 1.0,
                TimeControl::Bullet if rating >= 2200 => 4.0 / 5.0,
                TimeControl::Bullet if rating >= 2000 => 1.0 / 4.0,
                TimeControl::Bullet if rating >= 1800 => 1.0 / 7.0,
                _ => 1.0 / 20.0,
            }
        } else {
            1.0 // variant game
        };

        self.current_game.push(b'\n');

        let Closed01(rnd) = random::<Closed01<f64>>();
        let accept = min(self.white_elo, self.black_elo) >= 1500 && probability >= rnd;

        self.skip = !accept;
        Skip(self.skip)
    }

    fn san(&mut self, san: San) {
        if self.plies < MAX_PLIES {
            if self.plies > 0 {
                self.current_game.push(b' ');
            }

            self.current_game.extend(san.to_string().as_bytes());
            self.plies += 1;
        }
    }

    fn begin_variation(&mut self) -> Skip {
        Skip(true) // stay in the mainline
    }

    fn end_game(&mut self, _game: &'pgn [u8]) {
        if !self.skip && self.plies > 8 {
            if self.batch_size >= BATCH_SIZE {
                self.send();
            }

            if self.batch_size > 0 {
                self.batch.extend(b"\n\n\n");
            }

            self.batch.extend(&self.current_game);
            self.batch_size += 1;
        }
    }
}

fn main() {
    for arg in env::args().skip(1) {
        eprintln!("% indexing {} ...", arg);
        let file = File::open(&arg).expect("fopen");
        let pgn = unsafe { Mmap::map(&file).expect("mmap") };
        pgn.advise_memory_access(AccessPattern::Sequential).expect("madvise");

        let mut indexer = Indexer::new(&arg);
        Reader::new(&mut indexer, &pgn[..]).read_all();
        indexer.send(); // send last
    }
}
<commit_msg>coding style<commit_after>#![feature(try_trait)]

extern crate pgn_reader;
extern crate memmap;
extern crate madvise;
extern crate btoi;
extern crate rand;
extern crate reqwest;

use std::env;
use std::mem;
use std::cmp::min;
use std::fs::File;
use std::option::NoneError;
use std::io::Read;

use memmap::Mmap;
use madvise::{AccessPattern, AdviseMemory};
use pgn_reader::{Visitor, Skip, Reader, San};
use btoi::ParseIntegerError;
use rand::{random, Closed01};

const BATCH_SIZE: usize = 50;

const MAX_PLIES: usize = 50;

#[derive(Debug)]
enum TimeControl {
    UltraBullet,
    Bullet,
    Blitz,
    Rapid,
    Classical,
    Correspondence,
}

#[derive(Debug)]
struct TimeControlError;

impl From<NoneError> for TimeControlError {
    fn from(_: NoneError) -> TimeControlError {
        TimeControlError { }
    }
}

impl From<ParseIntegerError> for TimeControlError {
    fn from(_: ParseIntegerError) -> TimeControlError {
        TimeControlError { }
    }
}

impl TimeControl {
    fn from_seconds_and_increment(seconds: u64, increment: u64) -> TimeControl {
        let total = seconds + 40 * increment;

        if total < 30 {
            TimeControl::UltraBullet
        } else if total < 180 {
            TimeControl::Bullet
        } else if total < 480 {
            TimeControl::Blitz
        } else if total < 1500 {
            TimeControl::Rapid
        } else if total < 21_600 {
            TimeControl::Classical
        } else {
            TimeControl::Correspondence
        }
    }

    fn from_bytes(bytes: &[u8]) -> Result<TimeControl, TimeControlError> {
        if bytes == b"-" {
            return Ok(TimeControl::Correspondence);
        }

        let mut parts = bytes.splitn(2, |ch| *ch == b'+');
        let seconds = btoi::btou(parts.next()?)?;
        let increment = btoi::btou(parts.next()?)?;
        Ok(TimeControl::from_seconds_and_increment(seconds, increment))
    }
}

struct Indexer {
    context: String,

    white_elo: i16,
    black_elo: i16,
    time_control: TimeControl,
    skip: bool,

    current_game: Vec<u8>,
    plies: usize,
    standard: bool,

    batch: Vec<u8>,
    batch_size: usize,
}

impl Indexer {
    fn new(context: &str) -> Indexer {
        Indexer {
            context: context.into(),

            white_elo: 0,
            black_elo: 0,
            time_control: TimeControl::Correspondence,
            skip: true,

            current_game: Vec::new(),
            plies: 0,
            standard: true,

            batch: Vec::new(),
            batch_size: 0,
        }
    }

    fn send(&mut self) {
        if self.batch_size > 0 {
            self.batch_size = 0;

            let mut res = reqwest::Client::new()
                .put("http://localhost:9000/import/lichess")
                .body(mem::replace(&mut self.batch, Vec::new()))
                .send().expect("send batch");

            let mut answer = String::new();
            res.read_to_string(&mut answer).expect("decode response");
            println!("{}: {}", self.context, answer);
            assert!(res.status().is_success());
        }
    }
}

impl<'pgn> Visitor<'pgn> for Indexer {
    type Result = ();

    fn begin_game(&mut self) {
        self.current_game.clear();
        self.plies = 0;
    }

    fn begin_headers(&mut self) {
        self.white_elo = 0;
        self.black_elo = 0;
        self.time_control = TimeControl::Correspondence;
        self.standard = true;
    }

    fn header(&mut self, key: &'pgn [u8], value: &'pgn [u8]) {
        if key == b"WhiteElo" {
            self.white_elo = if value == b"?" { 0 } else { btoi::btoi(value).expect("WhiteElo") };
        } else if key == b"BlackElo" {
            self.black_elo = if value == b"?" { 0 } else { btoi::btoi(value).expect("BlackElo") };
        } else if key == b"TimeControl" {
            self.time_control = TimeControl::from_bytes(value).expect("TimeControl");
        } else if key == b"Variant" {
            self.standard = value == b"Standard";
            if self.standard {
                return; // we add this unconditionally later
            }
        }

        let (key, value) = if key == b"Site" {
            (&b"LichessID"[..], value.rsplitn(2, |ch| *ch == b'/').next().expect("Site"))
        } else {
            (key, value)
        };

        self.current_game.push(b'[');
        self.current_game.extend(key);
        self.current_game.extend(b" \"");
        self.current_game.extend(value);
        self.current_game.extend(b"\"]\n");
    }

    fn end_headers(&mut self) -> Skip {
        let rating = (self.white_elo + self.black_elo) / 2;

        let probability = if self.standard {
            self.current_game.extend(b"[Variant \"Standard\"]\n");

            match self.time_control {
                TimeControl::Correspondence | TimeControl::Classical => 1.0,
                TimeControl::Rapid if rating >= 2000 => 1.0,
                TimeControl::Rapid if rating >= 1800 => 2.0 / 5.0,
                TimeControl::Rapid => 1.0 / 8.0,
                TimeControl::Blitz if rating >= 2000 => 1.0,
                TimeControl::Blitz if rating >= 1800 => 1.0 / 4.0,
                TimeControl::Blitz => 1.0 / 15.0,
                TimeControl::Bullet if rating >= 2300 => 1.0,
                TimeControl::Bullet if rating >= 2200 => 4.0 / 5.0,
                TimeControl::Bullet if rating >= 2000 => 1.0 / 4.0,
                TimeControl::Bullet if rating >= 1800 => 1.0 / 7.0,
                _ => 1.0 / 20.0,
            }
        } else {
            1.0 // variant game
        };

        self.current_game.push(b'\n');

        let Closed01(rnd) = random::<Closed01<f64>>();
        let accept = min(self.white_elo, self.black_elo) >= 1500 && probability >= rnd;

        self.skip = !accept;
        Skip(self.skip)
    }

    fn san(&mut self, san: San) {
        if self.plies < MAX_PLIES {
            if self.plies > 0 {
                self.current_game.push(b' ');
            }

            self.current_game.extend(san.to_string().as_bytes());
            self.plies += 1;
        }
    }

    fn begin_variation(&mut self) -> Skip {
        Skip(true) // stay in the mainline
    }

    fn end_game(&mut self, _game: &'pgn [u8]) {
        if !self.skip && self.plies > 8 {
            if self.batch_size >= BATCH_SIZE {
                self.send();
            }

            if self.batch_size > 0 {
                self.batch.extend(b"\n\n\n");
            }

            self.batch.extend(&self.current_game);
            self.batch_size += 1;
        }
    }
}

fn main() {
    for arg in env::args().skip(1) {
        eprintln!("% indexing {} ...", arg);
        let file = File::open(&arg).expect("fopen");
        let pgn = unsafe { Mmap::map(&file).expect("mmap") };
        pgn.advise_memory_access(AccessPattern::Sequential).expect("madvise");

        let mut indexer = Indexer::new(&arg);
        Reader::new(&mut indexer, &pgn[..]).read_all();
        indexer.send(); // send last
    }
}
<|endoftext|>


<commit_before>use {Euclid, Point};
use point::Euclidean;

/// Clustering via the *k*-means algorithm (aka Lloyd's algorithm).
///
/// > *k*-means clustering aims to partition *n* observations into *k*
/// clusters in which each observation belongs to the cluster with the
/// nearest mean, serving as a prototype of the cluster.wikipedia
///
/// This is a heuristic, iterative approximation to the true optimal
/// assignment. The parameters used to control the approximation can
/// be set via `KmeansBuilder`.
///
/// # Examples
///
/// ```rust
/// use cogset::{Euclid, Kmeans};
///
/// let data = [Euclid([0.0, 0.0]),
///             Euclid([1.0, 0.5]),
///             Euclid([0.2, 0.2]),
///             Euclid([0.3, 0.8]),
///             Euclid([0.0, 1.0])];
/// let k = 3;
///
/// let kmeans = Kmeans::new(&data, k);
///
/// println!("{:?}", kmeans.clusters());
/// ```

pub struct Kmeans<T> {
    assignments: Vec<usize>,
    centres: Vec<Euclid<T>>,
    iterations: usize,
    converged: bool,
}

impl<T> Kmeans<T>
    where Euclid<T>: Point + Euclidean + Clone
{
    /// Run k-means on `data` with the default settings.
    pub fn new(data: &[Euclid<T>], k: usize) -> Kmeans<T> {
        KmeansBuilder::new().kmeans(data, k)
    }

    /// Retrieve the means and the clusters themselves that this
    /// *k*-means instance computed.
    ///
    /// The clusters are represented by vectors of indexes into the
    /// original data.
    pub fn clusters(&self) -> Vec<(Euclid<T>, Vec<usize>)> {
        let mut ret = self.centres.iter().cloned().map(|c| (c, vec![])).collect::<Vec<_>>();

        for (idx, &assign) in self.assignments.iter().enumerate() {
            ret[assign].1.push(idx);
        }

        ret
    }

    /// Return whether the algorithm converged, and how many steps
    /// that took.
    ///
    /// `Ok` is returned if the algorithm did meet the tolerance
    /// criterion, and `Err` if it reached the iteration limit
    /// instead.
    pub fn converged(&self) -> Result<usize, usize> {
        if self.converged {
            Ok(self.iterations)
        } else {
            Err(self.iterations)
        }
    }
}

const DEFAULT_MAX_ITER: usize = 100;
const DEFAULT_TOL: f64 = 1e-6;

/// A builder for *k*-means to provide control over parameters for the
/// algorithm.
///
/// This allows one to tweak settings like the tolerance and the
/// number of iterations.
///
/// # Examples
///
/// ```rust
/// use cogset::{Euclid, KmeansBuilder};
///
/// let data = [Euclid([0.0, 0.0]),
///             Euclid([1.0, 0.5]),
///             Euclid([0.2, 0.2]),
///             Euclid([0.3, 0.8]),
///             Euclid([0.0, 1.0])];
///
/// let k = 3;
///
/// // we want the means extra precise.
/// let tol = 1e-12;
/// let kmeans = KmeansBuilder::new().tolerance(tol).kmeans(&data, k);
///
/// println!("{:?}", kmeans.clusters());
/// ```
pub struct KmeansBuilder {
    tol: f64,
    max_iter: usize,
}

impl KmeansBuilder {
    /// Create a default `KmeansBuilder`
    pub fn new() -> KmeansBuilder {
        KmeansBuilder {
            tol: DEFAULT_TOL,
            max_iter: DEFAULT_MAX_ITER,
        }
    }

    /// Set the tolerance used to decide if the iteration has
    /// converged to `tol`.
    pub fn tolerance(self, tol: f64) -> KmeansBuilder {
        KmeansBuilder { tol: tol, .. self }
    }
    /// Set the maximum number of iterations to run before aborting to
    /// `max_iter`.
    pub fn max_iter(self, max_iter: usize) -> KmeansBuilder {
        KmeansBuilder { max_iter: max_iter, .. self }
    }

    /// Run *k*-means with the given settings.
    ///
    /// This is functionally identical to `Kmeans::new`, other than
    /// the internal parameters differing.
    pub fn kmeans<T>(self, data: &[Euclid<T>], k: usize) -> Kmeans<T>
        where Euclid<T>: Point + Euclidean + Clone
    {
        assert!(2 <= k && k < data.len());

        let n = data.len();
        let mut assignments = vec![!0; n];
        let mut costs = vec![0.0; n];
        let mut centres = data.iter().take(k).cloned().collect::<Vec<_>>();
        let mut counts = vec![0; k];
        update_assignments(data, &mut assignments, &mut counts, &mut costs, &centres);
        let mut objective = costs.iter().fold(0.0, |a, b| a + *b);

        let mut converged = false;
        let mut iter = 0;
        while iter < self.max_iter {
            update_centres(data, &assignments, &counts, &mut centres);
            update_assignments(data, &mut assignments, &mut counts, &mut costs, &centres);

            let new_objective = costs.iter().fold(0.0, |a, b| a + *b);

            if (new_objective - objective).abs() < self.tol {
                converged = true;
                break
            }

            objective = new_objective;
            iter += 1
        }

        Kmeans {
            assignments: assignments,
            centres: centres,
            iterations: iter,
            converged: converged,
        }
    }
}

fn update_assignments<T>(data: &[Euclid<T>],
                         assignments: &mut [usize], counts: &mut [usize], costs: &mut [f64],
                         centres: &[Euclid<T>])
    where Euclid<T>: Point + Euclidean + Clone
{
    use std::f64::INFINITY as INF;

    for place in counts.iter_mut() { *place = 0 }

    for ((point, assign), cost) in data.iter().zip(assignments.iter_mut()).zip(costs.iter_mut()) {
        let mut min_dist = INF;
        let mut index = 0;
        for (i, c) in centres.iter().enumerate() {
            let dist = point.dist(c);
            if dist < min_dist {
                min_dist = dist;
                index = i;
            }
        }

        *cost = min_dist;
        *assign = index;
        counts[index] += 1;
    }
}

fn update_centres<T>(data: &[Euclid<T>],
                     assignments: &[usize], counts: &[usize],
                     centres: &mut [Euclid<T>])
    where Euclid<T>: Point + Euclidean + Clone
{
    for place in centres.iter_mut() { *place = <Euclid<T>>::zero() }

    for (point, assign) in data.iter().zip(assignments.iter()) {
        centres[*assign].add(point)
    }
    for (place, scale) in centres.iter_mut().zip(counts.iter()) {
        place.scale(1.0 / *scale as f64)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use Euclid;
    use rand::{XorShiftRng,Rng};

    #[test]
    fn smoke() {
        let points = [Euclid([0.0, 0.0]),
                      Euclid([1.0, 0.5]),
                      Euclid([0.2, 0.2]),
                      Euclid([0.3, 0.8]),
                      Euclid([0.0, 1.0]),
                      ];

        let res = Kmeans::new(&points, 3);
        let mut clusters = res.clusters();
        for &mut (_, ref mut v) in &mut clusters {
            v.sort()
        }
        clusters.sort_by(|a, b| a.1.cmp(&b.1));
        assert_eq!(clusters,
                   [(Euclid([0.1, 0.1]), vec![0, 2]),
                    (Euclid([1.0, 0.5]), vec![1]),
                    (Euclid([0.15, 0.9]), vec![3, 4])]);

        assert_eq!(res.converged(), Ok(2));
    }
    #[test]
    fn no_converge() {
        let mut rng = XorShiftRng::new_unseeded();
        let points = (0..100)
            .map(|_| Euclid([rng.gen()]))
            .collect::<Vec<Euclid<[f64; 1]>>>();

        let res = KmeansBuilder::new().tolerance(1e-18).max_iter(2).kmeans(&points, 4);

        assert_eq!(res.converged(), Err(2))
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use super::Kmeans;
    use Euclid;
    use rand::{XorShiftRng,Rng};
    use test::Bencher;
    macro_rules! benches {
        ($($name: ident, $k: expr, $n: expr;)*) => {
            $(
                #[bench]
                fn $name(b: &mut Bencher) {
                    let k = $k;
                    let n = $n;

                    let mut rng = XorShiftRng::new_unseeded();
                    let points = rng
                        .gen_iter::<f64>()
                        .take(n)
                        .map(|f| Euclid([f]))
                        .collect::<Vec<_>>();

                    b.iter(|| Kmeans::new(&points, k))
                }
                )*
        }
    }

    benches! {
        k003_n00010,   3,    10;
        k003_n00100,   3,   100;
        k003_n01000,   3,  1000;
        k003_n10000,   3, 10000;

        k010_n00100,  10,   100;
        k010_n01000,  10,  1000;
        k010_n10000,  10, 10000;

        k100_n01000, 100,  1000;
        // too slow:
        // k100_n10000, 100, 10000;
    }
}
<commit_msg>kmeans: compute as few sqrt as possible.<commit_after>use {Euclid, Point};
use point::Euclidean;

/// Clustering via the *k*-means algorithm (aka Lloyd's algorithm).
///
/// > *k*-means clustering aims to partition *n* observations into *k*
/// clusters in which each observation belongs to the cluster with the
/// nearest mean, serving as a prototype of the cluster.wikipedia
///
/// This is a heuristic, iterative approximation to the true optimal
/// assignment. The parameters used to control the approximation can
/// be set via `KmeansBuilder`.
///
/// # Examples
///
/// ```rust
/// use cogset::{Euclid, Kmeans};
///
/// let data = [Euclid([0.0, 0.0]),
///             Euclid([1.0, 0.5]),
///             Euclid([0.2, 0.2]),
///             Euclid([0.3, 0.8]),
///             Euclid([0.0, 1.0])];
/// let k = 3;
///
/// let kmeans = Kmeans::new(&data, k);
///
/// println!("{:?}", kmeans.clusters());
/// ```

pub struct Kmeans<T> {
    assignments: Vec<usize>,
    centres: Vec<Euclid<T>>,
    iterations: usize,
    converged: bool,
}

impl<T> Kmeans<T>
    where Euclid<T>: Point + Euclidean + Clone
{
    /// Run k-means on `data` with the default settings.
    pub fn new(data: &[Euclid<T>], k: usize) -> Kmeans<T> {
        KmeansBuilder::new().kmeans(data, k)
    }

    /// Retrieve the means and the clusters themselves that this
    /// *k*-means instance computed.
    ///
    /// The clusters are represented by vectors of indexes into the
    /// original data.
    pub fn clusters(&self) -> Vec<(Euclid<T>, Vec<usize>)> {
        let mut ret = self.centres.iter().cloned().map(|c| (c, vec![])).collect::<Vec<_>>();

        for (idx, &assign) in self.assignments.iter().enumerate() {
            ret[assign].1.push(idx);
        }

        ret
    }

    /// Return whether the algorithm converged, and how many steps
    /// that took.
    ///
    /// `Ok` is returned if the algorithm did meet the tolerance
    /// criterion, and `Err` if it reached the iteration limit
    /// instead.
    pub fn converged(&self) -> Result<usize, usize> {
        if self.converged {
            Ok(self.iterations)
        } else {
            Err(self.iterations)
        }
    }
}

const DEFAULT_MAX_ITER: usize = 100;
const DEFAULT_TOL: f64 = 1e-6;

/// A builder for *k*-means to provide control over parameters for the
/// algorithm.
///
/// This allows one to tweak settings like the tolerance and the
/// number of iterations.
///
/// # Examples
///
/// ```rust
/// use cogset::{Euclid, KmeansBuilder};
///
/// let data = [Euclid([0.0, 0.0]),
///             Euclid([1.0, 0.5]),
///             Euclid([0.2, 0.2]),
///             Euclid([0.3, 0.8]),
///             Euclid([0.0, 1.0])];
///
/// let k = 3;
///
/// // we want the means extra precise.
/// let tol = 1e-12;
/// let kmeans = KmeansBuilder::new().tolerance(tol).kmeans(&data, k);
///
/// println!("{:?}", kmeans.clusters());
/// ```
pub struct KmeansBuilder {
    tol: f64,
    max_iter: usize,
}

impl KmeansBuilder {
    /// Create a default `KmeansBuilder`
    pub fn new() -> KmeansBuilder {
        KmeansBuilder {
            tol: DEFAULT_TOL,
            max_iter: DEFAULT_MAX_ITER,
        }
    }

    /// Set the tolerance used to decide if the iteration has
    /// converged to `tol`.
    pub fn tolerance(self, tol: f64) -> KmeansBuilder {
        KmeansBuilder { tol: tol, .. self }
    }
    /// Set the maximum number of iterations to run before aborting to
    /// `max_iter`.
    pub fn max_iter(self, max_iter: usize) -> KmeansBuilder {
        KmeansBuilder { max_iter: max_iter, .. self }
    }

    /// Run *k*-means with the given settings.
    ///
    /// This is functionally identical to `Kmeans::new`, other than
    /// the internal parameters differing.
    pub fn kmeans<T>(self, data: &[Euclid<T>], k: usize) -> Kmeans<T>
        where Euclid<T>: Point + Euclidean + Clone
    {
        assert!(2 <= k && k < data.len());

        let n = data.len();
        let mut assignments = vec![!0; n];
        let mut costs = vec![0.0; n];
        let mut centres = data.iter().take(k).cloned().collect::<Vec<_>>();
        let mut counts = vec![0; k];
        update_assignments(data, &mut assignments, &mut counts, &mut costs, &centres);
        let mut objective = costs.iter().fold(0.0, |a, b| a + *b);

        let mut converged = false;
        let mut iter = 0;
        while iter < self.max_iter {
            update_centres(data, &assignments, &counts, &mut centres);
            update_assignments(data, &mut assignments, &mut counts, &mut costs, &centres);

            let new_objective = costs.iter().fold(0.0, |a, b| a + *b);

            if (new_objective - objective).abs() < self.tol {
                converged = true;
                break
            }

            objective = new_objective;
            iter += 1
        }

        Kmeans {
            assignments: assignments,
            centres: centres,
            iterations: iter,
            converged: converged,
        }
    }
}

fn update_assignments<T>(data: &[Euclid<T>],
                         assignments: &mut [usize], counts: &mut [usize], costs: &mut [f64],
                         centres: &[Euclid<T>])
    where Euclid<T>: Point + Euclidean + Clone
{
    use std::f64::INFINITY as INF;

    for place in counts.iter_mut() { *place = 0 }

    for ((point, assign), cost) in data.iter().zip(assignments.iter_mut()).zip(costs.iter_mut()) {
        let mut min_dist = INF;
        let mut index = 0;
        for (i, c) in centres.iter().enumerate() {
            // we can use the square of the distance here
            let dist = point.dist2(c);
            if dist < min_dist {
                min_dist = dist;
                index = i;
            }
        }

        // but we need to make sure we're storing the right cost.
        *cost = min_dist.sqrt();
        *assign = index;
        counts[index] += 1;
    }
}

fn update_centres<T>(data: &[Euclid<T>],
                     assignments: &[usize], counts: &[usize],
                     centres: &mut [Euclid<T>])
    where Euclid<T>: Point + Euclidean + Clone
{
    for place in centres.iter_mut() { *place = <Euclid<T>>::zero() }

    for (point, assign) in data.iter().zip(assignments.iter()) {
        centres[*assign].add(point)
    }
    for (place, scale) in centres.iter_mut().zip(counts.iter()) {
        place.scale(1.0 / *scale as f64)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use Euclid;
    use rand::{XorShiftRng,Rng};

    #[test]
    fn smoke() {
        let points = [Euclid([0.0, 0.0]),
                      Euclid([1.0, 0.5]),
                      Euclid([0.2, 0.2]),
                      Euclid([0.3, 0.8]),
                      Euclid([0.0, 1.0]),
                      ];

        let res = Kmeans::new(&points, 3);
        let mut clusters = res.clusters();
        for &mut (_, ref mut v) in &mut clusters {
            v.sort()
        }
        clusters.sort_by(|a, b| a.1.cmp(&b.1));
        assert_eq!(clusters,
                   [(Euclid([0.1, 0.1]), vec![0, 2]),
                    (Euclid([1.0, 0.5]), vec![1]),
                    (Euclid([0.15, 0.9]), vec![3, 4])]);

        assert_eq!(res.converged(), Ok(2));
    }
    #[test]
    fn no_converge() {
        let mut rng = XorShiftRng::new_unseeded();
        let points = (0..100)
            .map(|_| Euclid([rng.gen()]))
            .collect::<Vec<Euclid<[f64; 1]>>>();

        let res = KmeansBuilder::new().tolerance(1e-18).max_iter(2).kmeans(&points, 4);

        assert_eq!(res.converged(), Err(2))
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use super::Kmeans;
    use Euclid;
    use rand::{XorShiftRng,Rng};
    use test::Bencher;
    macro_rules! benches {
        ($($name: ident, $k: expr, $n: expr;)*) => {
            $(
                #[bench]
                fn $name(b: &mut Bencher) {
                    let k = $k;
                    let n = $n;

                    let mut rng = XorShiftRng::new_unseeded();
                    let points = rng
                        .gen_iter::<f64>()
                        .take(n)
                        .map(|f| Euclid([f]))
                        .collect::<Vec<_>>();

                    b.iter(|| Kmeans::new(&points, k))
                }
                )*
        }
    }

    benches! {
        k003_n00010,   3,    10;
        k003_n00100,   3,   100;
        k003_n01000,   3,  1000;
        k003_n10000,   3, 10000;

        k010_n00100,  10,   100;
        k010_n01000,  10,  1000;
        k010_n10000,  10, 10000;

        k100_n01000, 100,  1000;
        // too slow:
        // k100_n10000, 100, 10000;
    }
}
<|endoftext|>


<commit_before>use super::*;

impl Editor {
    /// Goto a given position
    #[inline]
    pub fn goto(&mut self, (x, y): (usize, usize)) {
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Get the position of the next char
    #[inline]
    pub fn next_pos(&self) -> (usize, usize) {
        // TODO: Add numerals
        if self.x() == self.text[self.y()].len() {
            if self.y() < self.text.len() - 1 {
                (0, self.y() + 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() + 1, self.y())
        }
    }

    /// Get the position of previous char
    #[inline]
    pub fn previous_pos(&self) -> (usize, usize) {
        if self.x() == 0 {
            if self.y() > 0 {
                (self.text[self.y() - 1].len(), self.y() - 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() - 1, self.y())
        }
    }

    /// Goto the next char
    #[inline]
    pub fn goto_next(&mut self) {
        let p = self.next_pos();
        self.goto(p);
    }
    /// Goto the previous char
    #[inline]
    pub fn goto_previous(&mut self) {
        let p = self.previous_pos();
        self.goto(p);
    }

    /// Get the position of the right char
    #[inline]
    pub fn right_pos(&self, n: usize) -> (usize, usize) {
        let x = self.x() + n;

        if x > self.text[self.y()].len() {
            (self.text[self.y()].len(), self.y())
        } else {
            (x, self.y())
        }
    }
    /// Goto the right char
    #[inline]
    pub fn goto_right(&mut self, n: usize) {
        self.cursor_mut().x = self.right_pos(n).0;
    }

    /// Get the position of the left char
    #[inline]
    pub fn left_pos(&self, n: usize) -> (usize, usize) {
        if n <= self.x() {
            (self.x() - n, self.y())
        } else {
            (0, self.y())
        }
    }
    /// Goto the left char
    #[inline]
    pub fn goto_left(&mut self, n: usize) {
        self.cursor_mut().x = self.left_pos(n).0;
    }

    /// Get the position of the char above the cursor
    #[inline]
    pub fn up_pos(&self, n: usize) -> (usize, usize) {
        if n <= self.y() {
            (self.cursor().x, self.y() - n)
        } else {
            (self.cursor().x, 0)
        }
    }
    /// Go a char up
    #[inline]
    pub fn goto_up(&mut self, n: usize) {
        let p = self.up_pos(n);
        self.goto(p);
    }

    /// Get the position under the char
    #[inline]
    pub fn down_pos(&self, n: usize) -> (usize, usize) {
        let y = self.y() + n;

        if y >= self.text.len() {
            (self.cursor().x, self.text.len() - 1)
        } else {
            (self.cursor().x, y)
        }
    }

    /// Go down
    #[inline]
    pub fn goto_down(&mut self, n: usize) {
        let p = self.down_pos(n);
        self.goto(p);
    }

    /// Get the position of the end of the line
    #[inline]
    pub fn ln_end_pos(&self) -> (usize, usize) {
        (self.text[self.y()].len(), self.y())
    }

    /// Goto line end
    #[inline]
    pub fn goto_ln_end(&mut self) {
        let p = self.ln_end_pos();
        self.goto(p);
    }
}
<commit_msg>Simplify and refactor<commit_after>use super::*;

impl Editor {
    /// Goto a given position
    #[inline]
    pub fn goto(&mut self, (x, y): (usize, usize)) {
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Get the position of the next char
    #[inline]
    pub fn next_pos(&self) -> (usize, usize) {
        // TODO: Add numerals
        if self.x() == self.text[self.y()].len() {
            if self.y() < self.text.len() - 1 {
                (0, self.y() + 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() + 1, self.y())
        }
    }

    /// Get the position of previous char
    #[inline]
    pub fn previous_pos(&self) -> (usize, usize) {
        if self.x() == 0 {
            if self.y() > 0 {
                (self.text[self.y() - 1].len(), self.y() - 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() - 1, self.y())
        }
    }

    /// Goto the next char
    #[inline]
    pub fn goto_next(&mut self) {
        let p = self.next_pos();
        self.goto(p);
    }
    /// Goto the previous char
    #[inline]
    pub fn goto_previous(&mut self) {
        let p = self.previous_pos();
        self.goto(p);
    }

    /// Get the position of the right char
    #[inline]
    pub fn right_pos(&self, n: usize) -> (usize, usize) {
        (self.x() + n, self.y())
    }
    /// Goto the right char
    #[inline]
    pub fn goto_right(&mut self, n: usize) {
        self.cursor_mut().x = self.right_pos(n).0;
    }

    /// Get the position of the left char
    #[inline]
    pub fn left_pos(&self, n: usize) -> (usize, usize) {
        if n <= self.x() {
            (self.x() - n, self.y())
        } else {
            (0, self.y())
        }
    }
    /// Goto the left char
    #[inline]
    pub fn goto_left(&mut self, n: usize) {
        self.cursor_mut().x = self.left_pos(n).0;
    }

    /// Get the position of the char above the cursor
    #[inline]
    pub fn up_pos(&self, n: usize) -> (usize, usize) {
        if n <= self.y() {
            (self.cursor().x, self.y() - n)
        } else {
            (self.cursor().x, 0)
        }
    }
    /// Go a char up
    #[inline]
    pub fn goto_up(&mut self, n: usize) {
        let p = self.up_pos(n);
        self.goto(p);
    }

    /// Get the position under the char
    #[inline]
    pub fn down_pos(&self, n: usize) -> (usize, usize) {
        (self.cursor().x, self.y() + n)
    }

    /// Go down
    #[inline]
    pub fn goto_down(&mut self, n: usize) {
        let p = self.down_pos(n);
        self.goto(p);
    }

    /// Get the position of the end of the line
    #[inline]
    pub fn ln_end_pos(&self) -> (usize, usize) {
        (self.text[self.y()].len(), self.y())
    }

    /// Goto line end
    #[inline]
    pub fn goto_ln_end(&mut self) {
        let p = self.ln_end_pos();
        self.goto(p);
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use eutil::fptr_is_null;
use libc::{c_int};
use std::mem;
use string::{cef_string_userfree_utf8_alloc,cef_string_userfree_utf8_free,cef_string_utf8_set};
use types::{cef_string_list_t,cef_string_t};

//cef_string_list

#[no_mangle]
extern "C" fn cef_string_list_alloc() -> *mut cef_string_list_t {
    unsafe {
         let lt: Box<Vec<*mut cef_string_t>> = box vec!();
         mem::transmute(lt)
    }
}

#[no_mangle]
extern "C" fn cef_string_list_size(lt: *const cef_string_list_t) -> c_int {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return 0; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        v.len() as c_int
    }
}

#[no_mangle]
extern "C" fn cef_string_list_append(lt: *mut cef_string_list_t, value: *const cef_string_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        let cs = cef_string_userfree_utf8_alloc();
        cef_string_utf8_set(mem::transmute((*value).str), (*value).length, cs, 1);
        v.push(cs);
    }
}

#[no_mangle]
extern "C" fn cef_string_list_value(lt: *mut cef_string_list_t, index: c_int, value: *mut cef_string_t) -> c_int {
    unsafe {
        if index < 0 || fptr_is_null(mem::transmute(lt)) { return 0; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        if index as uint > v.len() - 1 { return 0; }
        let cs = v.get(index as uint);
        cef_string_utf8_set(mem::transmute((**cs).str), (**cs).length, value, 1)
    }
}

#[no_mangle]
extern "C" fn cef_string_list_clear(lt: *mut cef_string_list_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        if v.len() == 0 { return; }
        let mut cs;
        while v.len() != 0 {
            cs = v.pop();
            cef_string_userfree_utf8_free(cs.unwrap());
        }
    }
}

#[no_mangle]
extern "C" fn cef_string_list_free(lt: *mut cef_string_list_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        cef_string_list_clear(lt);
        drop(v);
    }
}
<commit_msg>embedding: cef_string_list_copy()<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use eutil::fptr_is_null;
use libc::{c_int};
use std::mem;
use string::{cef_string_userfree_utf8_alloc,cef_string_userfree_utf8_free,cef_string_utf8_set};
use types::{cef_string_list_t,cef_string_t};

//cef_string_list

#[no_mangle]
extern "C" fn cef_string_list_alloc() -> *mut cef_string_list_t {
    unsafe {
         let lt: Box<Vec<*mut cef_string_t>> = box vec!();
         mem::transmute(lt)
    }
}

#[no_mangle]
extern "C" fn cef_string_list_size(lt: *const cef_string_list_t) -> c_int {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return 0; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        v.len() as c_int
    }
}

#[no_mangle]
extern "C" fn cef_string_list_append(lt: *mut cef_string_list_t, value: *const cef_string_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        let cs = cef_string_userfree_utf8_alloc();
        cef_string_utf8_set(mem::transmute((*value).str), (*value).length, cs, 1);
        v.push(cs);
    }
}

#[no_mangle]
extern "C" fn cef_string_list_value(lt: *mut cef_string_list_t, index: c_int, value: *mut cef_string_t) -> c_int {
    unsafe {
        if index < 0 || fptr_is_null(mem::transmute(lt)) { return 0; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        if index as uint > v.len() - 1 { return 0; }
        let cs = v.get(index as uint);
        cef_string_utf8_set(mem::transmute((**cs).str), (**cs).length, value, 1)
    }
}

#[no_mangle]
extern "C" fn cef_string_list_clear(lt: *mut cef_string_list_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        if v.len() == 0 { return; }
        let mut cs;
        while v.len() != 0 {
            cs = v.pop();
            cef_string_userfree_utf8_free(cs.unwrap());
        }
    }
}

#[no_mangle]
extern "C" fn cef_string_list_free(lt: *mut cef_string_list_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        cef_string_list_clear(lt);
        drop(v);
    }
}

#[no_mangle]
extern "C" fn cef_string_list_copy(lt: *mut cef_string_list_t) -> *mut cef_string_list_t {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return 0 as *mut cef_string_list_t; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        let lt2 = cef_string_list_alloc();
        for cs in v.iter() {
            cef_string_list_append(lt2, mem::transmute((*cs)));
        }
        lt2
    }
}
<|endoftext|>


<commit_before>// copyright 2017 Kaz Wesley

//! Classic Blake in a Rustic setting

#![no_std]

extern crate block_buffer;
pub extern crate digest;

mod consts;

use block_buffer::BlockBuffer;
use core::mem;
use digest::generic_array::GenericArray;
pub use digest::Digest;

#[derive(Debug, Clone, Copy)]
#[repr(C)]
struct State<T> {
    h: [T; 8],
    t: [T; 2],
    nullt: bool,
}

macro_rules! define_compressor {
    ($compressor:ident, $word:ident, $Bufsz:ty, $deserializer:path, $uval:expr,
     $rounds:expr, $shift0:expr, $shift1:expr, $shift2: expr, $shift3: expr) => {
        #[derive(Clone, Copy, Debug)]
        struct $compressor {
            state: State<$word>,
        }

        impl $compressor {
            fn increase_count(&mut self, count: $word) {
                let (new_t0, carry) = self.state.t[0].overflowing_add(count * 8);
                self.state.t[0] = new_t0;
                if carry {
                    self.state.t[1] += 1;
                }
            }

            fn put_block(&mut self, block: &GenericArray<u8, $Bufsz>) {
                const U: [$word; 16] = $uval;

                #[inline(always)]
                fn g(
                    v: &mut [$word; 16],
                    m: &[$word; 16],
                    sigma: &[u8; 16],
                    a: usize,
                    b: usize,
                    c: usize,
                    d: usize,
                    e: usize,
                ) {
                    v[a] = v[a]
                        .wrapping_add(m[sigma[e] as usize] ^ U[sigma[e + 1] as usize])
                        .wrapping_add(v[b]);
                    v[d] = (v[d] ^ v[a]).rotate_right($shift0);
                    v[c] = v[c].wrapping_add(v[d]);
                    v[b] = (v[b] ^ v[c]).rotate_right($shift1);
                    v[a] = v[a]
                        .wrapping_add(m[sigma[e + 1] as usize] ^ U[sigma[e] as usize])
                        .wrapping_add(v[b]);
                    v[d] = (v[d] ^ v[a]).rotate_right($shift2);
                    v[c] = v[c].wrapping_add(v[d]);
                    v[b] = (v[b] ^ v[c]).rotate_right($shift3);
                }

                let mut m = [0; 16];
                for (mx, b) in m.iter_mut().zip(block.chunks(mem::size_of::<$word>())) {
                    *mx = $deserializer(b);
                }

                let mut v = [0; 16];
                &v[..8].copy_from_slice(&self.state.h);
                &v[8..].copy_from_slice(&U[..8]);

                // don't xor t when the block is only padding
                if !self.state.nullt {
                    v[12] ^= self.state.t[0];
                    v[13] ^= self.state.t[0];
                    v[14] ^= self.state.t[1];
                    v[15] ^= self.state.t[1];
                }

                for sigma in &SIGMA[..$rounds] {
                    // column step
                    g(&mut v, &m, sigma, 0, 4, 8, 12, 0);
                    g(&mut v, &m, sigma, 1, 5, 9, 13, 2);
                    g(&mut v, &m, sigma, 2, 6, 10, 14, 4);
                    g(&mut v, &m, sigma, 3, 7, 11, 15, 6);
                    // diagonal step
                    g(&mut v, &m, sigma, 0, 5, 10, 15, 8);
                    g(&mut v, &m, sigma, 1, 6, 11, 12, 10);
                    g(&mut v, &m, sigma, 2, 7, 8, 13, 12);
                    g(&mut v, &m, sigma, 3, 4, 9, 14, 14);
                }

                for (i, vx) in v.iter().enumerate() {
                    self.state.h[i % 8] ^= *vx;
                }
            }
        }
    };
}

macro_rules! define_hasher {
    ($name:ident, $word:ident, $buf:expr, $Bufsz:ty, $bits:expr, $Bytes:ident,
     $serializer:path, $compressor:ident, $iv:expr) => {
        #[derive(Clone)]
        pub struct $name {
            compressor: $compressor,
            buffer: BlockBuffer<$Bufsz>,
        }

        impl core::fmt::Debug for $name {
            fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
                f.debug_struct("Blake")
                    .field("compressor", &self.compressor)
                    .field("buffer.position()", &self.buffer.position())
                    .finish()
            }
        }

        impl Default for $name {
            fn default() -> Self {
                Self {
                    compressor: $compressor {
                        state: State::<$word> {
                            h: $iv,
                            t: [0; 2],
                            nullt: false,
                        },
                    },
                    buffer: BlockBuffer::default(),
                }
            }
        }

        impl digest::BlockInput for $name {
            type BlockSize = $Bytes;
        }

        impl digest::Input for $name {
            fn input<T: AsRef<[u8]>>(&mut self, data: T) {
                let compressor = &mut self.compressor;
                self.buffer.input(data.as_ref(), |block| {
                    compressor.increase_count((mem::size_of::<$word>() * 16) as $word);
                    compressor.put_block(block);
                });
            }
        }

        impl digest::FixedOutput for $name {
            type OutputSize = $Bytes;

            fn fixed_result(self) -> GenericArray<u8, $Bytes> {
                let mut compressor = self.compressor;
                let mut buffer = self.buffer;

                compressor.increase_count(buffer.position() as $word);

                let mut msglen = [0u8; $buf / 8];
                $serializer(&mut msglen[..$buf / 16], compressor.state.t[1]);
                $serializer(&mut msglen[$buf / 16..], compressor.state.t[0]);

                let footerlen = 1 + 2 * mem::size_of::<$word>();

                // low bit indicates full-length variant
                let isfull = ($bits == 8 * mem::size_of::<[$word; 8]>()) as u8;
                // high bit indicates fit with no padding
                let exactfit = if buffer.position() + footerlen != $buf {
                    0x00
                } else {
                    0x80
                };
                let magic = isfull | exactfit;

                // if header won't fit in last data block, pad to the end and start a new one
                let extra_block = buffer.position() + footerlen > $buf;
                if extra_block {
                    let pad = $buf - buffer.position();
                    buffer.input(&PADDING[..pad], |block| compressor.put_block(block));
                    debug_assert_eq!(buffer.position(), 0);
                }

                // pad last block up to footer start point
                compressor.state.nullt = buffer.position() == 0;
                // skip begin-padding byte if continuing padding
                let x = extra_block as usize;
                let (start, end) = (x, x + ($buf - footerlen - buffer.position()));
                buffer.input(&PADDING[start..end], |_| unreachable!());
                buffer.input(&[magic], |_| unreachable!());
                buffer.input(&msglen, |block| compressor.put_block(block));
                debug_assert_eq!(buffer.position(), 0);

                let mut out = GenericArray::default();
                for (h, out) in compressor
                    .state
                    .h
                    .iter()
                    .zip(out.chunks_mut(mem::size_of::<$word>()))
                {
                    $serializer(out, *h);
                }
                out
            }
        }

        impl digest::Reset for $name {
            fn reset(&mut self) {
                *self = Self::default()
            }
        }
    };
}

use block_buffer::byteorder::{ByteOrder, BE};
use consts::{
    BLAKE224_IV, BLAKE256_IV, BLAKE256_U, BLAKE384_IV, BLAKE512_IV, BLAKE512_U, PADDING, SIGMA,
};
use digest::generic_array::typenum::{U128, U28, U32, U48, U64};

#[cfg_attr(rustfmt, rustfmt_skip)]
define_compressor!(Compressor256, u32, U64, BE::read_u32, BLAKE256_U, 14, 16, 12, 8, 7);

#[cfg_attr(rustfmt, rustfmt_skip)]
define_hasher!(Blake224, u32, 64, U64, 224, U28, BE::write_u32, Compressor256, BLAKE224_IV);

#[cfg_attr(rustfmt, rustfmt_skip)]
define_hasher!(Blake256, u32, 64, U64, 256, U32, BE::write_u32, Compressor256, BLAKE256_IV);

#[cfg_attr(rustfmt, rustfmt_skip)]
define_compressor!(Compressor512, u64, U128, BE::read_u64, BLAKE512_U, 16, 32, 25, 16, 11);

#[cfg_attr(rustfmt, rustfmt_skip)]
define_hasher!(Blake384, u64, 128, U128, 384, U48, BE::write_u64, Compressor512, BLAKE384_IV);

#[cfg_attr(rustfmt, rustfmt_skip)]
define_hasher!(Blake512, u64, 128, U128, 512, U64, BE::write_u64, Compressor512, BLAKE512_IV);
<commit_msg>use chunks_exact<commit_after>// copyright 2017 Kaz Wesley

//! Classic Blake in a Rustic setting

#![no_std]

extern crate block_buffer;
pub extern crate digest;

mod consts;

use block_buffer::BlockBuffer;
use core::mem;
use digest::generic_array::GenericArray;
pub use digest::Digest;

#[derive(Debug, Clone, Copy)]
#[repr(C)]
struct State<T> {
    h: [T; 8],
    t: [T; 2],
    nullt: bool,
}

macro_rules! define_compressor {
    ($compressor:ident, $word:ident, $Bufsz:ty, $deserializer:path, $uval:expr,
     $rounds:expr, $shift0:expr, $shift1:expr, $shift2: expr, $shift3: expr) => {
        #[derive(Clone, Copy, Debug)]
        struct $compressor {
            state: State<$word>,
        }

        impl $compressor {
            fn increase_count(&mut self, count: $word) {
                let (new_t0, carry) = self.state.t[0].overflowing_add(count * 8);
                self.state.t[0] = new_t0;
                if carry {
                    self.state.t[1] += 1;
                }
            }

            fn put_block(&mut self, block: &GenericArray<u8, $Bufsz>) {
                const U: [$word; 16] = $uval;

                #[inline(always)]
                fn g(
                    v: &mut [$word; 16],
                    m: &[$word; 16],
                    sigma: &[u8; 16],
                    a: usize,
                    b: usize,
                    c: usize,
                    d: usize,
                    e: usize,
                ) {
                    v[a] = v[a]
                        .wrapping_add(m[sigma[e] as usize] ^ U[sigma[e + 1] as usize])
                        .wrapping_add(v[b]);
                    v[d] = (v[d] ^ v[a]).rotate_right($shift0);
                    v[c] = v[c].wrapping_add(v[d]);
                    v[b] = (v[b] ^ v[c]).rotate_right($shift1);
                    v[a] = v[a]
                        .wrapping_add(m[sigma[e + 1] as usize] ^ U[sigma[e] as usize])
                        .wrapping_add(v[b]);
                    v[d] = (v[d] ^ v[a]).rotate_right($shift2);
                    v[c] = v[c].wrapping_add(v[d]);
                    v[b] = (v[b] ^ v[c]).rotate_right($shift3);
                }

                let mut m = [0; 16];
                for (mx, b) in m
                    .iter_mut()
                    .zip(block.chunks_exact(mem::size_of::<$word>()))
                {
                    *mx = $deserializer(b);
                }

                let mut v = [0; 16];
                &v[..8].copy_from_slice(&self.state.h);
                &v[8..].copy_from_slice(&U[..8]);

                // don't xor t when the block is only padding
                if !self.state.nullt {
                    v[12] ^= self.state.t[0];
                    v[13] ^= self.state.t[0];
                    v[14] ^= self.state.t[1];
                    v[15] ^= self.state.t[1];
                }

                for sigma in &SIGMA[..$rounds] {
                    // column step
                    g(&mut v, &m, sigma, 0, 4, 8, 12, 0);
                    g(&mut v, &m, sigma, 1, 5, 9, 13, 2);
                    g(&mut v, &m, sigma, 2, 6, 10, 14, 4);
                    g(&mut v, &m, sigma, 3, 7, 11, 15, 6);
                    // diagonal step
                    g(&mut v, &m, sigma, 0, 5, 10, 15, 8);
                    g(&mut v, &m, sigma, 1, 6, 11, 12, 10);
                    g(&mut v, &m, sigma, 2, 7, 8, 13, 12);
                    g(&mut v, &m, sigma, 3, 4, 9, 14, 14);
                }

                for (i, vx) in v.iter().enumerate() {
                    self.state.h[i % 8] ^= *vx;
                }
            }
        }
    };
}

macro_rules! define_hasher {
    ($name:ident, $word:ident, $buf:expr, $Bufsz:ty, $bits:expr, $Bytes:ident,
     $serializer:path, $compressor:ident, $iv:expr) => {
        #[derive(Clone)]
        pub struct $name {
            compressor: $compressor,
            buffer: BlockBuffer<$Bufsz>,
        }

        impl core::fmt::Debug for $name {
            fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
                f.debug_struct("Blake")
                    .field("compressor", &self.compressor)
                    .field("buffer.position()", &self.buffer.position())
                    .finish()
            }
        }

        impl Default for $name {
            fn default() -> Self {
                Self {
                    compressor: $compressor {
                        state: State::<$word> {
                            h: $iv,
                            t: [0; 2],
                            nullt: false,
                        },
                    },
                    buffer: BlockBuffer::default(),
                }
            }
        }

        impl digest::BlockInput for $name {
            type BlockSize = $Bytes;
        }

        impl digest::Input for $name {
            fn input<T: AsRef<[u8]>>(&mut self, data: T) {
                let compressor = &mut self.compressor;
                self.buffer.input(data.as_ref(), |block| {
                    compressor.increase_count((mem::size_of::<$word>() * 16) as $word);
                    compressor.put_block(block);
                });
            }
        }

        impl digest::FixedOutput for $name {
            type OutputSize = $Bytes;

            fn fixed_result(self) -> GenericArray<u8, $Bytes> {
                let mut compressor = self.compressor;
                let mut buffer = self.buffer;

                compressor.increase_count(buffer.position() as $word);

                let mut msglen = [0u8; $buf / 8];
                $serializer(&mut msglen[..$buf / 16], compressor.state.t[1]);
                $serializer(&mut msglen[$buf / 16..], compressor.state.t[0]);

                let footerlen = 1 + 2 * mem::size_of::<$word>();

                // low bit indicates full-length variant
                let isfull = ($bits == 8 * mem::size_of::<[$word; 8]>()) as u8;
                // high bit indicates fit with no padding
                let exactfit = if buffer.position() + footerlen != $buf {
                    0x00
                } else {
                    0x80
                };
                let magic = isfull | exactfit;

                // if header won't fit in last data block, pad to the end and start a new one
                let extra_block = buffer.position() + footerlen > $buf;
                if extra_block {
                    let pad = $buf - buffer.position();
                    buffer.input(&PADDING[..pad], |block| compressor.put_block(block));
                    debug_assert_eq!(buffer.position(), 0);
                }

                // pad last block up to footer start point
                compressor.state.nullt = buffer.position() == 0;
                // skip begin-padding byte if continuing padding
                let x = extra_block as usize;
                let (start, end) = (x, x + ($buf - footerlen - buffer.position()));
                buffer.input(&PADDING[start..end], |_| unreachable!());
                buffer.input(&[magic], |_| unreachable!());
                buffer.input(&msglen, |block| compressor.put_block(block));
                debug_assert_eq!(buffer.position(), 0);

                let mut out = GenericArray::default();
                for (h, out) in compressor
                    .state
                    .h
                    .iter()
                    .zip(out.chunks_exact_mut(mem::size_of::<$word>()))
                {
                    $serializer(out, *h);
                }
                out
            }
        }

        impl digest::Reset for $name {
            fn reset(&mut self) {
                *self = Self::default()
            }
        }
    };
}

use block_buffer::byteorder::{ByteOrder, BE};
use consts::{
    BLAKE224_IV, BLAKE256_IV, BLAKE256_U, BLAKE384_IV, BLAKE512_IV, BLAKE512_U, PADDING, SIGMA,
};
use digest::generic_array::typenum::{U128, U28, U32, U48, U64};

#[cfg_attr(rustfmt, rustfmt_skip)]
define_compressor!(Compressor256, u32, U64, BE::read_u32, BLAKE256_U, 14, 16, 12, 8, 7);

#[cfg_attr(rustfmt, rustfmt_skip)]
define_hasher!(Blake224, u32, 64, U64, 224, U28, BE::write_u32, Compressor256, BLAKE224_IV);

#[cfg_attr(rustfmt, rustfmt_skip)]
define_hasher!(Blake256, u32, 64, U64, 256, U32, BE::write_u32, Compressor256, BLAKE256_IV);

#[cfg_attr(rustfmt, rustfmt_skip)]
define_compressor!(Compressor512, u64, U128, BE::read_u64, BLAKE512_U, 16, 32, 25, 16, 11);

#[cfg_attr(rustfmt, rustfmt_skip)]
define_hasher!(Blake384, u64, 128, U128, 384, U48, BE::write_u64, Compressor512, BLAKE384_IV);

#[cfg_attr(rustfmt, rustfmt_skip)]
define_hasher!(Blake512, u64, 128, U128, 512, U64, BE::write_u64, Compressor512, BLAKE512_IV);
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>learn rust in 5 minutes<commit_after>fn add2(x:i32, y:i32) -> i32 {
    x + y
}

fn main() {
    println!("Hello, world!");
    let x:i32 = 1; //immutable binding
    let y:i32 = 13i32; //integer suffix
    let f:f64 = 1.3f64; // float suffix

    //type inference
    let implicit_x = 1;
    let implicit_f = 1.3;

    let sum = x + y + 13;

    let mut a = 1;
    a = 5;
    a += 2;

    let x:&str = "hello world"; // string literal
    println!("{} {}", f, x);

    let s:String = "hello world".to_string();

    // just a pointer to something that does contain a string: s
    let s_slice:&str = &*s;
    println!("{}", s);

    // fixed size ints array
    let four_ints:[i32; 4] = [1,2,3,4];
    // a dynamic int array, vector array
    let mut vec:Vec<i32> = vec![1,2,3,4];
    vec.push(5);

    // just a pointer to something that does contains a vector/array
    let slice_vec:&[i32] = &*vec;

    // print debug style
    println!("{:?} {:?}", vec, slice_vec);

    // tuple: a fixed size set of values
    let d:(i32, &str, f64) = (1, "hello", 3.4);

    // destructuring let
    let (e, f, g) = d;
    println!("{} {} {}", e, f, g);
    // indexing
    println!("{}", d.1);

    // struc w/ named field
    struct Point {
        x:i32,
        y:i32,
    }
    let origin:Point = Point{x:0, y:0};

    // struc w/ unamed field: tuple struct
    struct Point2(i32, i32);
    let origin2:Point2 = Point2(0,0);

    // c like enum
    enum Direction {
        l,
        r,
        u,
        d
    }
    let up = Direction::u;

}
<|endoftext|>


<commit_before>/// Eases forming of `QVariantLists` ([`QVariant`](struct.QVariant.html) of array).
///
/// To be more precise, macro generates Vec<QVariant> which implements Into<QVariant>.
/// # Examples
/// ```
/// # #[macro_use] extern crate qml;
/// # use qml::*;
/// # fn main() {
/// let shortcut: QVariant = qvarlist![["John", [2, 2]], ["Ivan", [10, 0]], ["Mary", [0, 1]]].into();
/// # }
/// ```
#[macro_export]
macro_rules! qvarlist{
    (__ $v:ident, [$($inside:tt)*], $($rest:tt)*) => {
        $v.push(qvarlist!($($inside)*).into());
        qvarlist!(__ $v, $($rest)*);
    };
    (__ $v:ident, [$($inside:tt)*]) => {
        $v.push(qvarlist!($($inside)*).into());
    };
    (__ $v:ident, $varname:expr, $($rest:tt)*) => {
        $v.push($varname.into());
        qvarlist!(__ $v, $($rest)*);
    };
    (__ $v:ident, $varname:expr) => {
        $v.push($varname.into());
    };
    ($($rest:tt)*) => {{
        let mut v: Vec<QVariant> = Vec::new();
        qvarlist!(__ v, $($rest)*);
        v
    }};
}

#[doc(hidden)]
#[macro_export]
macro_rules! __gen_signals{
    (fn $signalname:ident ( $( $signalvar:ident : $signalqtype:ident ),* ); $($rest:tt)*) =>{
        pub fn $signalname(&self, $( $signalvar: $signalqtype ),*){
            let mut vec: Vec<QVariant> = Vec::new();
            $(
                let $signalvar: $signalqtype = $signalvar;
                vec.push($signalvar.into());
            )*
            emit_signal(self, stringify!($signalname), vec);
        }

        __gen_signals!($($rest)*);
    };
    () => ();
}

/// Marks the structure to be able to be used in Qt meta-object system.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate qml;
/// # use qml::*;
/// pub struct Example;
///
/// impl Example {
///     pub fn simple_receiver(&mut self) {
///         // This is a function that also will be a slot
///     }
/// }
///
/// Q_OBJECT!(
/// pub Example as QExample{
///     signals:
///         fn simple_signal(s: String);
///     slots:
///         fn simple_receiver();
///     properties:
///         name: String; read: get_name, write: set_name, notify: name_changed;
/// });
///
/// ...
///
/// # fn main() {
/// let mut qqae = QmlEngine::new();
/// let mut qobject = QExample::new(Example);
/// qobject.simple_signal("Hi from Rust!".into());
/// # }
/// ```
#[macro_export]
macro_rules! Q_OBJECT{
(
    pub $obj:ty as $wrapper:ident{
        signals:
        $(fn $signalname:ident ( $( $signalvar:ident : $signalqtype:ident ),* );)*

        slots:
        $(fn $slotname:ident ( $( $slotvar:ident : $slotqtype:ident ),* );)*

        properties:
        $($propname:ident : $proptype:ident; read: $read_slot:ident, write: $write_slot:ident,
             notify: $notify_sig:ident;)*
    }) =>{

        fn get_atomic_ptr<T>(o: &mut T) -> ::std::sync::atomic::AtomicPtr<T> {
            ::std::sync::atomic::AtomicPtr::new(o as *mut T)
        }

        fn load_borrow<T>(ptr: ::std::sync::atomic::AtomicPtr<T>) -> &'static mut T {
            unsafe { &mut *ptr.load(::std::sync::atomic::Ordering::Relaxed) }
        }

        pub struct $wrapper{
            origin: Box<$obj>,
            ptr: Option<QObject>,
            $($propname: $proptype,)*
        }

        impl ::std::ops::Deref for $wrapper {
            type Target = $obj;

            fn deref(&self) -> &$obj {
                let ref b: Box<$obj> = self.origin;
                b.as_ref()
            }
        }

        impl ::std::ops::DerefMut for $wrapper {
            fn deref_mut<'a>(&'a mut self) -> &'a mut $obj {
                self.origin.as_mut()
            }
        }

        impl $wrapper{
            __gen_signals!($(fn $signalname ( $( $signalvar : $signalqtype ),* );)*
            $(fn $notify_sig ();)*);

            pub fn new(origin: $obj, $($propname: $proptype),*) -> Box<Self>{
                unsafe{
                    let mut local = $wrapper{
                        origin: Box::new(origin),
                        ptr: None,
                        $($propname: $propname,)*
                    };
                    let mut local = Box::new(local);
                    let qobj = QObject::new(&mut *local);
                    local.ptr = Some(qobj);
                    local
                }
            }

            $(pub fn $read_slot(&self) -> $proptype {
                self.$propname.clone()
            }

            pub fn $write_slot(&mut self, input: $proptype) {
                self.$propname = input
            })*
        }

        impl QObjectMacro for $wrapper{
            fn qslot_call(&mut self, name: &str, args: Vec<QVariant>) {
                fn next_or_panic(qt: Option<QVariant>) -> QVariant{
                    if let Some(o) = qt {
                        o
                    }else {
                        panic!("Not enough parameters to call a slot")
                    }
                }
                match name {
                    $(stringify!($slotname) => {
                        let mut iter = args.into_iter();
                        $(
                            let next = next_or_panic (iter.next());
                            let $slotvar: $slotqtype = next.into();
                        )*
                        self.$slotname ($($slotvar),*);
                    },)*
                    $(stringify!($read_slot) => {
                        let sending = self.$read_slot ();
                    },
                    stringify!($write_slot) => {
                        let mut iter = args.into_iter();
                        let next = next_or_panic (iter.next());
                        let property: $proptype = next.into();
                        self.$write_slot (property);
                    },)*
                    _ => panic!("Unrecognized slot call: {}", name)
                }
            }

            fn qmeta(&self) -> (Vec<(&'static str, i32, Vec<i32>)>,
                                Vec<(&'static str, i32, i32, Vec<i32>)>,
                                Vec<(&'static str, i32, &'static str, &'static str, &'static str)>,
                                &'static str){
                use qml::qtypes::*;
                let mut signals = Vec::new();
                $(
                    let mut argc = 0;
                    let mut mttypes = Vec::new();
                    $(
                        argc += 1;
                        mttypes.push($signalqtype::metatype() as i32);
                    )*
                    signals.push((stringify!($signalname), argc, mttypes));
                )*
                let mut slots = Vec::new();
                $(
                    let mut argc = 0;
                    let mut mttypes = Vec::new();
                    $(
                        argc += 1;
                        mttypes.push($slotqtype::metatype() as i32);
                    )*
                    slots.push((stringify!($slotname), 43, argc, mttypes));
                )*
                let mut props: Vec<(&'static str, i32, &'static str, &'static str, &'static str)> = Vec::new();
                $(
                    props.push((stringify!($propname), $proptype::metatype() as i32, stringify!($read_slot),
                               stringify!($write_slot), stringify!($notify_sig)));
                )*
                (signals, slots, props, stringify!($obj))
            }

            fn get_qobj(&self) -> &QObject{
                self.ptr.as_ref().unwrap()
            }
        }
    };
}

// #[macro_export]
// macro_rules! __listmodel_helper{
//     (()$roletype:ident),*) => {
//         ($(v.next().unwrap().into()),*)
//     }
// }

/// Generates a wrapper for [`QListModel`](struct.QListModel.html) for static typing and easier management.
///
/// # Examples
/// ```
/// # #[macro_use] extern crate qml;
/// # use qml::*;
/// Q_LISTMODEL!{
///     pub QTestModel {
///         name: &str,
///         number: i32,
///     }
/// }
///
/// ...
///
/// # fn main() {
/// let mut qqae = QmlEngine::new();
/// let mut qalm = QTestModel::new();
/// qalm.insert_row("John", 42);
/// qalm.insert_row("Oak", 505);
/// // `&QTestModel` implements `Into<QVariant>`
/// qqae.set_and_store_property("listModel", &qalm);
///
/// qqae.load_file("examples/listmodel.qml");
/// qalm.set_data(vec![("OMG", 13317), ("HACKED", 228)]);
/// qqae.exec();
/// # }
/// ```
#[macro_export]
macro_rules! Q_LISTMODEL{
    (pub $wrapper:ident{
        $($rolename:ident : $roletype:ty,)*
    }) => {
        pub struct $wrapper {
            qalm: Box<QListModel<'static>>,
        }

        impl $wrapper {
            pub fn new() -> Self{
                $wrapper{ qalm: QListModel::new(&[$(stringify!($rolename)),*])}
            }

            /// Inserts a row into this model
            pub fn insert_row(&mut self, $($rolename : $roletype),*) {
                let mut vec = Vec::new();
                $(
                    vec.push($rolename.into());
                )*
                self.qalm.insert_row(vec.into_iter());
            }

            /// Gets an accoiated qvariant
            pub fn get_qvar(&self) -> QVariant{
                self.qalm.get_qvar()
            }

            /// Sets a specified data for this model
            pub fn set_data(&mut self, vec: Vec<($($roletype),*)>) {
                self.qalm.set_data(vec.into_iter()
                .map(|($($rolename),*)| {
                    let mut vec = Vec::new();
                    $(
                        vec.push($rolename.into());
                    )*
                    vec
                }).collect::<Vec<Vec<QVariant>>>())
            }

            /// View contents of this model as a slice of rows of QVariants
            pub fn view_raw_data(&self) -> &[Vec<QVariant>]{
                self.qalm.view_data()
            }

            /// View contents of this model as a row
            pub fn view_data(&self) -> Vec<($($roletype),*)>{
                let view = self.qalm.view_data();
                view.into_iter().map(|v| {
                    let mut v = v.iter();
                    $(
                        let $rolename = v.next().unwrap().into();
                    )*
                    ($($rolename),*)
                }).collect()
            }
        }

        impl<'a, 'b> From<&'a $wrapper> for QVariant {
            fn from(i: &$wrapper) -> QVariant {
                i.get_qvar()
            }
        }
    }
}
<commit_msg>Replaced Option with pure type<commit_after>/// Eases forming of `QVariantLists` ([`QVariant`](struct.QVariant.html) of array).
///
/// To be more precise, macro generates Vec<QVariant> which implements Into<QVariant>.
/// # Examples
/// ```
/// # #[macro_use] extern crate qml;
/// # use qml::*;
/// # fn main() {
/// let shortcut: QVariant = qvarlist![["John", [2, 2]], ["Ivan", [10, 0]], ["Mary", [0, 1]]].into();
/// # }
/// ```
#[macro_export]
macro_rules! qvarlist{
    (__ $v:ident, [$($inside:tt)*], $($rest:tt)*) => {
        $v.push(qvarlist!($($inside)*).into());
        qvarlist!(__ $v, $($rest)*);
    };
    (__ $v:ident, [$($inside:tt)*]) => {
        $v.push(qvarlist!($($inside)*).into());
    };
    (__ $v:ident, $varname:expr, $($rest:tt)*) => {
        $v.push($varname.into());
        qvarlist!(__ $v, $($rest)*);
    };
    (__ $v:ident, $varname:expr) => {
        $v.push($varname.into());
    };
    ($($rest:tt)*) => {{
        let mut v: Vec<QVariant> = Vec::new();
        qvarlist!(__ v, $($rest)*);
        v
    }};
}

#[doc(hidden)]
#[macro_export]
macro_rules! __gen_signals{
    (fn $signalname:ident ( $( $signalvar:ident : $signalqtype:ident ),* ); $($rest:tt)*) =>{
        pub fn $signalname(&self, $( $signalvar: $signalqtype ),*){
            let mut vec: Vec<QVariant> = Vec::new();
            $(
                let $signalvar: $signalqtype = $signalvar;
                vec.push($signalvar.into());
            )*
            emit_signal(self, stringify!($signalname), vec);
        }

        __gen_signals!($($rest)*);
    };
    () => ();
}

/// Marks the structure to be able to be used in Qt meta-object system.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate qml;
/// # use qml::*;
/// pub struct Example;
///
/// impl Example {
///     pub fn simple_receiver(&mut self) {
///         // This is a function that also will be a slot
///     }
/// }
///
/// Q_OBJECT!(
/// pub Example as QExample{
///     signals:
///         fn simple_signal(s: String);
///     slots:
///         fn simple_receiver();
///     properties:
///         name: String; read: get_name, write: set_name, notify: name_changed;
/// });
///
/// ...
///
/// # fn main() {
/// let mut qqae = QmlEngine::new();
/// let mut qobject = QExample::new(Example);
/// qobject.simple_signal("Hi from Rust!".into());
/// # }
/// ```
#[macro_export]
macro_rules! Q_OBJECT{
(
    pub $obj:ty as $wrapper:ident{
        signals:
        $(fn $signalname:ident ( $( $signalvar:ident : $signalqtype:ident ),* );)*

        slots:
        $(fn $slotname:ident ( $( $slotvar:ident : $slotqtype:ident ),* );)*

        properties:
        $($propname:ident : $proptype:ident; read: $read_slot:ident, write: $write_slot:ident,
             notify: $notify_sig:ident;)*
    }) =>{

        fn get_atomic_ptr<T>(o: &mut T) -> ::std::sync::atomic::AtomicPtr<T> {
            ::std::sync::atomic::AtomicPtr::new(o as *mut T)
        }

        fn load_borrow<T>(ptr: ::std::sync::atomic::AtomicPtr<T>) -> &'static mut T {
            unsafe { &mut *ptr.load(::std::sync::atomic::Ordering::Relaxed) }
        }

        pub struct $wrapper{
            origin: Box<$obj>,
            ptr: QObject,
            $($propname: $proptype,)*
        }

        impl ::std::ops::Deref for $wrapper {
            type Target = $obj;

            fn deref(&self) -> &$obj {
                let ref b: Box<$obj> = self.origin;
                b.as_ref()
            }
        }

        impl ::std::ops::DerefMut for $wrapper {
            fn deref_mut<'a>(&'a mut self) -> &'a mut $obj {
                self.origin.as_mut()
            }
        }

        impl $wrapper{
            __gen_signals!($(fn $signalname ( $( $signalvar : $signalqtype ),* );)*
            $(fn $notify_sig ();)*);

            pub fn new(origin: $obj, $($propname: $proptype),*) -> Box<Self>{
                unsafe{
                    let mut local = $wrapper{
                        origin: Box::new(origin),
                        ptr: ::std::mem::uninitialized(),
                        $($propname: $propname,)*
                    };
                    let mut local = Box::new(local);
                    let qobj = QObject::new(&mut *local);
                    ::std::ptr::write(&mut local.ptr, qobj);
                    local
                }
            }

            $(pub fn $read_slot(&self) -> $proptype {
                self.$propname.clone()
            }

            pub fn $write_slot(&mut self, input: $proptype) {
                self.$propname = input
            })*
        }

        impl QObjectMacro for $wrapper{
            fn qslot_call(&mut self, name: &str, args: Vec<QVariant>) {
                fn next_or_panic(qt: Option<QVariant>) -> QVariant{
                    if let Some(o) = qt {
                        o
                    }else {
                        panic!("Not enough parameters to call a slot")
                    }
                }
                match name {
                    $(stringify!($slotname) => {
                        let mut iter = args.into_iter();
                        $(
                            let next = next_or_panic (iter.next());
                            let $slotvar: $slotqtype = next.into();
                        )*
                        self.$slotname ($($slotvar),*);
                    },)*
                    $(stringify!($read_slot) => {
                        let sending = self.$read_slot ();
                    },
                    stringify!($write_slot) => {
                        let mut iter = args.into_iter();
                        let next = next_or_panic (iter.next());
                        let property: $proptype = next.into();
                        self.$write_slot (property);
                    },)*
                    _ => panic!("Unrecognized slot call: {}", name)
                }
            }

            fn qmeta(&self) -> (Vec<(&'static str, i32, Vec<i32>)>,
                                Vec<(&'static str, i32, i32, Vec<i32>)>,
                                Vec<(&'static str, i32, &'static str, &'static str, &'static str)>,
                                &'static str){
                use qml::qtypes::*;
                let mut signals = Vec::new();
                $(
                    let mut argc = 0;
                    let mut mttypes = Vec::new();
                    $(
                        argc += 1;
                        mttypes.push($signalqtype::metatype() as i32);
                    )*
                    signals.push((stringify!($signalname), argc, mttypes));
                )*
                let mut slots = Vec::new();
                $(
                    let mut argc = 0;
                    let mut mttypes = Vec::new();
                    $(
                        argc += 1;
                        mttypes.push($slotqtype::metatype() as i32);
                    )*
                    slots.push((stringify!($slotname), 43, argc, mttypes));
                )*
                let mut props: Vec<(&'static str, i32, &'static str, &'static str, &'static str)> = Vec::new();
                $(
                    props.push((stringify!($propname), $proptype::metatype() as i32, stringify!($read_slot),
                               stringify!($write_slot), stringify!($notify_sig)));
                )*
                (signals, slots, props, stringify!($obj))
            }

            fn get_qobj(&self) -> &QObject{
                &self.ptr
            }
        }
    };
}

// #[macro_export]
// macro_rules! __listmodel_helper{
//     (()$roletype:ident),*) => {
//         ($(v.next().unwrap().into()),*)
//     }
// }

/// Generates a wrapper for [`QListModel`](struct.QListModel.html) for static typing and easier management.
///
/// # Examples
/// ```
/// # #[macro_use] extern crate qml;
/// # use qml::*;
/// Q_LISTMODEL!{
///     pub QTestModel {
///         name: &str,
///         number: i32,
///     }
/// }
///
/// ...
///
/// # fn main() {
/// let mut qqae = QmlEngine::new();
/// let mut qalm = QTestModel::new();
/// qalm.insert_row("John", 42);
/// qalm.insert_row("Oak", 505);
/// // `&QTestModel` implements `Into<QVariant>`
/// qqae.set_and_store_property("listModel", &qalm);
///
/// qqae.load_file("examples/listmodel.qml");
/// qalm.set_data(vec![("OMG", 13317), ("HACKED", 228)]);
/// qqae.exec();
/// # }
/// ```
#[macro_export]
macro_rules! Q_LISTMODEL{
    (pub $wrapper:ident{
        $($rolename:ident : $roletype:ty,)*
    }) => {
        pub struct $wrapper {
            qalm: Box<QListModel<'static>>,
        }

        impl $wrapper {
            pub fn new() -> Self{
                $wrapper{ qalm: QListModel::new(&[$(stringify!($rolename)),*])}
            }

            /// Inserts a row into this model
            pub fn insert_row(&mut self, $($rolename : $roletype),*) {
                let mut vec = Vec::new();
                $(
                    vec.push($rolename.into());
                )*
                self.qalm.insert_row(vec.into_iter());
            }

            /// Gets an accoiated qvariant
            pub fn get_qvar(&self) -> QVariant{
                self.qalm.get_qvar()
            }

            /// Sets a specified data for this model
            pub fn set_data(&mut self, vec: Vec<($($roletype),*)>) {
                self.qalm.set_data(vec.into_iter()
                .map(|($($rolename),*)| {
                    let mut vec = Vec::new();
                    $(
                        vec.push($rolename.into());
                    )*
                    vec
                }).collect::<Vec<Vec<QVariant>>>())
            }

            /// View contents of this model as a slice of rows of QVariants
            pub fn view_raw_data(&self) -> &[Vec<QVariant>]{
                self.qalm.view_data()
            }

            /// View contents of this model as a row
            pub fn view_data(&self) -> Vec<($($roletype),*)>{
                let view = self.qalm.view_data();
                view.into_iter().map(|v| {
                    let mut v = v.iter();
                    $(
                        let $rolename = v.next().unwrap().into();
                    )*
                    ($($rolename),*)
                }).collect()
            }
        }

        impl<'a, 'b> From<&'a $wrapper> for QVariant {
            fn from(i: &$wrapper) -> QVariant {
                i.get_qvar()
            }
        }
    }
}
<|endoftext|>


<commit_before>use helpers;
use std::collections::HashMap;
use std::ops::Deref;

static MEMORY_FILE: &'static str = "/proc/meminfo";

fn str_to_string(s: &str) -> String {
    s.to_string()
}

pub fn read_usage() -> Result<String, String> {
    let content = helpers::read_file_to_string(MEMORY_FILE);
    match content {
        Err(err) => Err(err),
        Ok(s) => {
            let lines: Vec<String> = s.split('\n').map(str_to_string).collect();
            let mut stats: HashMap<String, String> = HashMap::new();
            for line in lines {
                let parts: Vec<String> = line.split_whitespace().map(str_to_string).collect();
                if parts.len() >= 2 {
                    let parts_deref = parts.deref();
                    let first: String = parts_deref[0].clone();
                    let second: String = parts_deref[1].clone();
                    stats.insert(first, second);
                }
            }

            Ok((*stats.get(&"MemTotal:".to_string()).unwrap()).clone())
        }
    }
}
<commit_msg>Simplified reading memory stats<commit_after>use helpers;
use std::collections::HashMap;
use std::ops::Deref;

static MEMORY_FILE: &'static str = "/proc/meminfo";

pub fn read_usage() -> Result<String, String> {
    let content = helpers::read_file_to_string(MEMORY_FILE);
    match content {
        Err(err) => Err(err),
        Ok(s) => {
            let lines: Vec<&str> = s.split('\n').collect();
            let mut stats: HashMap<&str, &str> = HashMap::new();
            for line in lines {
                let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
                let parts = parts.deref();
                if parts.len() >= 2 {
                    stats.insert(parts[0], parts[1]);
                }
            }

            Ok((*stats.get(&"MemTotal").unwrap()).to_string())
        }
    }
}
<|endoftext|>


<commit_before>#[derive(Queryable)]
pub struct Post {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub published: bool,
}<commit_msg>#10 Changed some travis confs for postgresql<commit_after>use super::schema::posts;

#[derive(Queryable)]
pub struct Post {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub published: bool,
}

#[derive(Insertable)]
#[table_name = "posts"]
pub struct NewPost<'a> {
    pub title: &'a str,
    pub body: &'a str,
}<|endoftext|>


<commit_before>extern crate nalgebra;
use nalgebra::*;
use om::cb::*;
use om::csv::*;
use std::rc::*;
use tick::*;
use std::f64::consts::*;

/// Keplerian Orbital Elements.
#[derive(Clone)]
pub struct KOE {
    /// Semi Major Axis.
    pub a: f64,
    /// Eccentricity.
    pub e: f64,
    /// Inclination.
    pub inc: f64,
    /// Longitude of Ascending Node.
    pub lan: f64,
    /// Argument of Periapsis.
    pub ap: f64,
    /// Mean anomaly.
    pub m0: f64,
    /// Mean motion.
    pub n: f64,
    /// A matrix that transforms a vector lying in i, j plane into a corresponding vector lying in the orbital plane
    /// defined by inc and lan.
    pub rot: Rot3<f64>,
    /// Reference to the central body that this object orbits.
    pub cb: Rc<CB>,
}

impl Tick for KOE {
    fn tick(&self, dt: f64) -> Self {
        KOE {
            a: self.a,
            e: self.e,
            inc: self.inc,
            lan: self.lan,
            ap: self.ap,
            m0: self.m0 + self.n * dt,
            n: self.n,
            rot: self.rot,
            cb: self.cb.clone(),
        }
    }
}

impl KOE {
    /// Construct KOE from orbital elements.
    pub fn new(a: f64, e: f64, inc: f64, lan: f64, ap: f64, m0: f64, cb: Rc<CB>) -> KOE {
        let mut rot = Rot3::new_identity(3);
        if approx_eq(&inc, &0.0) {
            if !approx_eq(&e, &0.0) {
                rot = Rot3::new(cb.k * ap);
            }
        } else {
            let lan_axisangle = cb.k * lan;
            let inc_axisangle = cb.i * inc;
            let ap_axisangle = cb.k * ap;
            rot = Rot3::new(lan_axisangle);
            rot = rot.prepend_rotation(&inc_axisangle);
            if !approx_eq(&e, &0.0) {
                rot = rot.prepend_rotation(&ap_axisangle);
            }
        }
        let n = (cb.mu/a.powf(3.0)).sqrt();
        KOE {
            a: a,
            e: e,
            inc: inc,
            lan: lan,
            ap: ap,
            m0: m0,
            n: n,
            rot: rot,
            cb: cb,
        }
    }

    /// Construct KOE from CSV.
    pub fn from_csv(csv: CSV) -> KOE {
        let r = csv.r;
        let v = csv.v;

        let mu = &csv.cb.mu;

        let h = cross(&r, &v);
        let e = cross(&v, &h)/ *mu - normalize(&r);
        let n = cross(&csv.cb.k, &h);

        let cos_inc = dot(&h, &csv.cb.k)/(norm(&h));
        let inc = if approx_eq(&cos_inc, &1.0) {
            0.0
        } else {
            cos_inc.acos()
        };

        let es = norm(&e);

        let mut lan = if dot(&n, &csv.cb.j) >= 0.0 {
            (dot(&n, &csv.cb.i)/norm(&n)).acos()
        } else {
            2.0*PI - (dot(&n, &csv.cb.i)/norm(&n)).acos()
        };

        let right = cross(&h, &n);
        let mut ap = if dot(&e, &right) >= 0.0 {
            (dot(&n, &e)/(norm(&n)*norm(&e))).acos()
        } else {
            2.0*PI - (dot(&n, &e)/(norm(&n)*norm(&e))).acos()
        };

        if approx_eq(&es, &0.0) {
            ap = 0.0;
        }
        if approx_eq(&inc, &0.0) {
            lan = 0.0;
            if !approx_eq(&es, &0.0) {
                ap = if dot(&e, &csv.cb.j) >= 0.0 {
                    (dot(&csv.cb.i, &e)/norm(&e)).acos()
                } else {
                    2.0*PI - (dot(&csv.cb.i, &e)/norm(&e)).acos()
                };
            } else {
                ap = 0.0;
            }
        }

        let mut ta = if dot(&r, &v) >= 0.0 {
            (dot(&e, &r)/(norm(&e)*norm(&r))).acos()
        } else {
            2.0*PI - (dot(&e, &r)/(norm(&e)*norm(&r))).acos()
        };

        if approx_eq(&es, &0.0) {
            // Compute argument of latitude
            if approx_eq(&inc, &0.0) {
                ta = if dot(&csv.cb.i, &v) <= 0.0 {
                    (dot(&csv.cb.i, &r)/(norm(&csv.cb.i)*norm(&r))).acos()
                } else {
                    2.0*PI - (dot(&csv.cb.i, &r)/(norm(&csv.cb.i)*norm(&r))).acos()
                }
            } else {
                ta = if dot(&n, &v) <= 0.0 {
                    (dot(&n, &r)/(norm(&n)*norm(&r))).acos()
                } else {
                    2.0*PI - (dot(&n, &r)/(norm(&n)*norm(&r))).acos()
                }
            }
        }

        let ea = 2.0*((ta/2.0).tan()/((1.0+es)/(1.0-es)).sqrt()).atan();
        let m0 = ea - es * ea.sin();
        let a = 1.0/(2.0/norm(&r) - sqnorm(&v)/mu);
        KOE::new(a, es, inc, lan, ap, m0, csv.cb.clone())
    }
}
<commit_msg>Use FRU syntax in Tick implementation for KOE<commit_after>extern crate nalgebra;
use nalgebra::*;
use om::cb::*;
use om::csv::*;
use std::rc::*;
use tick::*;
use std::f64::consts::*;

/// Keplerian Orbital Elements.
#[derive(Clone)]
pub struct KOE {
    /// Semi Major Axis.
    pub a: f64,
    /// Eccentricity.
    pub e: f64,
    /// Inclination.
    pub inc: f64,
    /// Longitude of Ascending Node.
    pub lan: f64,
    /// Argument of Periapsis.
    pub ap: f64,
    /// Mean anomaly.
    pub m0: f64,
    /// Mean motion.
    pub n: f64,
    /// A matrix that transforms a vector lying in i, j plane into a corresponding vector lying in the orbital plane
    /// defined by inc and lan.
    pub rot: Rot3<f64>,
    /// Reference to the central body that this object orbits.
    pub cb: Rc<CB>,
}

impl Tick for KOE {
    fn tick(&self, dt: f64) -> Self {
        KOE {
            m0: self.m0 + self.n * dt,
            cb: self.cb.clone(),
            ..*self
        }
    }
}

impl KOE {
    /// Construct KOE from orbital elements.
    pub fn new(a: f64, e: f64, inc: f64, lan: f64, ap: f64, m0: f64, cb: Rc<CB>) -> KOE {
        let mut rot = Rot3::new_identity(3);
        if approx_eq(&inc, &0.0) {
            if !approx_eq(&e, &0.0) {
                rot = Rot3::new(cb.k * ap);
            }
        } else {
            let lan_axisangle = cb.k * lan;
            let inc_axisangle = cb.i * inc;
            let ap_axisangle = cb.k * ap;
            rot = Rot3::new(lan_axisangle);
            rot = rot.prepend_rotation(&inc_axisangle);
            if !approx_eq(&e, &0.0) {
                rot = rot.prepend_rotation(&ap_axisangle);
            }
        }
        let n = (cb.mu/a.powf(3.0)).sqrt();
        KOE {
            a: a,
            e: e,
            inc: inc,
            lan: lan,
            ap: ap,
            m0: m0,
            n: n,
            rot: rot,
            cb: cb,
        }
    }

    /// Construct KOE from CSV.
    pub fn from_csv(csv: CSV) -> KOE {
        let r = csv.r;
        let v = csv.v;

        let mu = &csv.cb.mu;

        let h = cross(&r, &v);
        let e = cross(&v, &h)/ *mu - normalize(&r);
        let n = cross(&csv.cb.k, &h);

        let cos_inc = dot(&h, &csv.cb.k)/(norm(&h));
        let inc = if approx_eq(&cos_inc, &1.0) {
            0.0
        } else {
            cos_inc.acos()
        };

        let es = norm(&e);

        let mut lan = if dot(&n, &csv.cb.j) >= 0.0 {
            (dot(&n, &csv.cb.i)/norm(&n)).acos()
        } else {
            2.0*PI - (dot(&n, &csv.cb.i)/norm(&n)).acos()
        };

        let right = cross(&h, &n);
        let mut ap = if dot(&e, &right) >= 0.0 {
            (dot(&n, &e)/(norm(&n)*norm(&e))).acos()
        } else {
            2.0*PI - (dot(&n, &e)/(norm(&n)*norm(&e))).acos()
        };

        if approx_eq(&es, &0.0) {
            ap = 0.0;
        }
        if approx_eq(&inc, &0.0) {
            lan = 0.0;
            if !approx_eq(&es, &0.0) {
                ap = if dot(&e, &csv.cb.j) >= 0.0 {
                    (dot(&csv.cb.i, &e)/norm(&e)).acos()
                } else {
                    2.0*PI - (dot(&csv.cb.i, &e)/norm(&e)).acos()
                };
            } else {
                ap = 0.0;
            }
        }

        let mut ta = if dot(&r, &v) >= 0.0 {
            (dot(&e, &r)/(norm(&e)*norm(&r))).acos()
        } else {
            2.0*PI - (dot(&e, &r)/(norm(&e)*norm(&r))).acos()
        };

        if approx_eq(&es, &0.0) {
            // Compute argument of latitude
            if approx_eq(&inc, &0.0) {
                ta = if dot(&csv.cb.i, &v) <= 0.0 {
                    (dot(&csv.cb.i, &r)/(norm(&csv.cb.i)*norm(&r))).acos()
                } else {
                    2.0*PI - (dot(&csv.cb.i, &r)/(norm(&csv.cb.i)*norm(&r))).acos()
                }
            } else {
                ta = if dot(&n, &v) <= 0.0 {
                    (dot(&n, &r)/(norm(&n)*norm(&r))).acos()
                } else {
                    2.0*PI - (dot(&n, &r)/(norm(&n)*norm(&r))).acos()
                }
            }
        }

        let ea = 2.0*((ta/2.0).tan()/((1.0+es)/(1.0-es)).sqrt()).atan();
        let m0 = ea - es * ea.sin();
        let a = 1.0/(2.0/norm(&r) - sqnorm(&v)/mu);
        KOE::new(a, es, inc, lan, ap, m0, csv.cb.clone())
    }
}
<|endoftext|>