<commit_before>use combine::{ParseError, ParseResult, chainl1, many1, satisfy};
use combine::char::{alpha_num, letter, string};
use combine::primitives::{Parser, Stream};
use combine_language::{Identifier, LanguageDef, LanguageEnv};

use rsstreem::ast::*;

use std::ops::Deref;

type ParseFn<'a, I> = fn(&RsstreemEnv<'a, I>, I) -> ParseResult<Box<Ast>, I>;

struct RsstreemParser<'a: 'b, 'b, I>
    where I: Stream<Item = char> + 'b
{
    env: &'b RsstreemEnv<'a, I>,
    parser: ParseFn<'a, I>,
}

impl<'a, 'b, I> Parser for RsstreemParser<'a, 'b, I>
    where I: Stream<Item = char> + 'b
{
    type Input = I;
    type Output = Box<Ast>;

    fn parse_stream(&mut self, input: I) -> ParseResult<Self::Output, Self::Input> {
        (self.parser)(self.env, input)
    }
}

struct RsstreemEnv<'a, I>
    where I: Stream<Item = char>
{
    env: LanguageEnv<'a, I>,
}

impl<'a, I> Deref for RsstreemEnv<'a, I>
    where I: Stream<Item = char>
{
    type Target = LanguageEnv<'a, I>;

    fn deref(&self) -> &Self::Target {
        &self.env
    }
}

impl<'a, 'b, I> RsstreemEnv<'a, I>
    where I: Stream<Item = char>,
          I::Range: 'b
{
    fn parser(&'b self, parser: ParseFn<'a, I>) -> RsstreemParser<'a, 'b, I> {
        RsstreemParser {
            env: self,
            parser: parser,
        }
    }

    fn parse_integer(&self, input: I) -> ParseResult<Box<Ast>, I> {
        self.integer()
            .map(|x| Box::new(Ast::Int(x)))
            .parse_stream(input)
    }

    #[warn(dead_code)]
    pub fn integer64(&'b self) -> RsstreemParser<'a, 'b, I> {
        self.parser(RsstreemEnv::parse_integer)
    }

    fn parse_add(&self, input: I) -> ParseResult<Box<Ast>, I> {
        let plus_op = self.reserved_op("+")
            .map(|_| {
                move |lhs, rhs| {
                    Box::new(Ast::Op {
                                 op: Biop::Plus,
                                 lhs: lhs,
                                 rhs: rhs,
                             })
                }
            });

        chainl1(self.parser(RsstreemEnv::parse_integer), plus_op).parse_stream(input)
    }

    pub fn add(&'b self) -> RsstreemParser<'a, 'b, I> {
        self.parser(RsstreemEnv::parse_add)
    }
}

pub fn parse_code<'a>(code: &'a str) -> Result<Vec<Box<Ast>>, ParseError<&'a str>> {
    let streem_env =
        LanguageEnv::new(LanguageDef {
                             ident: Identifier {
                                 start: letter(),
                                 rest: alpha_num(),
                                 reserved: ["if",
                                            "else",
                                            "skip",
                                            "case",
                                            "emif",
                                            "return",
                                            "namespace",
                                            "class",
                                            "import",
                                            "def",
                                            "method",
                                            "new",
                                            "nil",
                                            "true",
                                            "false"]
                                         .iter()
                                         .map(|x| (*x).into())
                                         .collect(),
                             },
                             op: Identifier {
                                 start: satisfy(|c| "+-*/%=!<>&|)(:".chars().any(|x| x == c)),
                                 rest: satisfy(|c| "+-*/%=!<>&|)(:".chars().any(|x| x == c)),
                                 reserved: ["::", ":", "==", "=", "(", ")", "+", "->", "*", "/",
                                            "%", "!=", "<=", ">=", "<-", "->", ">", "<", "&&", "&"]
                                         .iter()
                                         .map(|x| (*x).into())
                                         .collect(),
                             },
                             comment_start: string("/*").map(|_| ()),
                             comment_end: string("*/").map(|_| ()),
                             comment_line: string("//").map(|_| ()),
                         });

    let env = RsstreemEnv { env: streem_env };

    env.white_space()
        .with(many1::<Vec<Box<Ast>>, _>(env.add()))
        .parse(code)
        .map(|(e, _)| e)
}
<commit_msg>[wip] Impl parser base<commit_after>#[warn(dead_code)] // Delete it later

use combine::{ParseError, ParseResult};
use combine::char::{alpha_num, letter, string};
use combine::combinator::*;
use combine::primitives::{Parser, Stream};
use combine_language::{Identifier, LanguageDef, LanguageEnv};

use rsstreem::ast::*;

use std::borrow::BorrowMut;
use std::cell::RefCell;
use std::ops::Deref;

type ParseFn<'a, I> = fn(&RsstreemEnv<'a, I>, I) -> ParseResult<Ast, I>;

struct RsstreemParser<'a: 'b, 'b, I>
    where I: Stream<Item = char> + 'b
{
    env: &'b RsstreemEnv<'a, I>,
    parser: ParseFn<'a, I>,
}

impl<'a, 'b, I> Parser for RsstreemParser<'a, 'b, I>
    where I: Stream<Item = char> + 'b
{
    type Input = I;
    type Output = Ast;

    fn parse_stream(&mut self, input: I) -> ParseResult<Self::Output, Self::Input> {
        (self.parser)(self.env, input)
    }
}

struct RsstreemEnv<'a, I>
    where I: Stream<Item = char>
{
    env: LanguageEnv<'a, I>,
}

impl<'a, I> Deref for RsstreemEnv<'a, I>
    where I: Stream<Item = char>
{
    type Target = LanguageEnv<'a, I>;

    fn deref(&self) -> &Self::Target {
        &self.env
    }
}

impl<'a, 'b, I> RsstreemEnv<'a, I>
    where I: Stream<Item = char>,
          I::Range: 'b
{
    fn parser(&'b self, parser: ParseFn<'a, I>) -> RsstreemParser<'a, 'b, I> {
        RsstreemParser {
            env: self,
            parser: parser,
        }
    }

    // ----- test code here
    fn parse_integer(&self, input: I) -> ParseResult<Ast, I> {
        self.integer().map(|x| Ast::Int(x)).parse_stream(input)
    }

    #[warn(dead_code)]
    pub fn integer64(&'b self) -> RsstreemParser<'a, 'b, I> {
        self.parser(RsstreemEnv::parse_integer)
    }

    fn parse_add(&self, input: I) -> ParseResult<Ast, I> {
        let plus_op = self.reserved_op("+")
            .map(|_| {
                move |lhs, rhs| {
                    Ast::Op {
                        op: Biop::Plus,
                        lhs: Box::new(lhs),
                        rhs: Box::new(rhs),
                    }
                }
            });

        chainl1(self.parser(RsstreemEnv::parse_integer), plus_op).parse_stream(input)
    }

    pub fn add(&'b self) -> RsstreemParser<'a, 'b, I> {
        self.parser(RsstreemEnv::parse_add)
    }
    // ----- /test code here

    fn parse_program(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_topstmts(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_topstmt_list(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_topstmt(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_stmts(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_stmt_list(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_stmt(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }

    fn parse_var(&self, input: I) -> ParseResult<Ast, I> {
        self.identifier().map(|v| Ast::Var(v)).parse_stream(input)
    }

    fn parse_fname(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_expr(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_condition(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_opt_else(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_opt_args(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_arg(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_args(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_primary(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_opt_block(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_pterm(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_pary(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_pstruct(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }
    fn parse_pattern(&self, input: I) -> ParseResult<Ast, I> {
        unimplemented!()
    }

    fn parse_cparam(&self, input: I) -> ParseResult<Ast, I> {
        let op_lambda = self.reserved_op("->")
            .map(|_| {
                     Ast::Plambda {
                         pat: Box::new(Ast::Null),
                         cond: Box::new(Ast::Null),
                         body: Box::new(Ast::Null),
                         next: RefCell::new(vec![]),
                     }
                 });

        let if_pattern = self.reserved("if")
            .with(self.parser(RsstreemEnv::parse_expr))
            .skip(self.reserved("->"))
            .map(|c| {
                     Ast::Plambda {
                         pat: Box::new(Ast::Null),
                         cond: Box::new(c),
                         body: Box::new(Ast::Null),
                         next: RefCell::new(vec![]),
                     }
                 });

        op_lambda.or(if_pattern).parse_stream(input)
    }

    fn parse_case_body(&self, input: I) -> ParseResult<Ast, I> {
        let top_case_stmt = self.reserved("case")
            .with(self.parser(RsstreemEnv::parse_cparam))
            .and(self.parser(RsstreemEnv::parse_stmts))
            .map(|(p, s)| match p {
                     Ast::Plambda {
                         pat,
                         cond,
                         body,
                         next,
                     } => {
                         Ast::Plambda {
                             pat: pat,
                             cond: cond,
                             body: Box::new(s),
                             next: next,
                         }
                     }
                     _ => panic!("not match case_body"),
                 });

        let seaq_case_stmt = self.parser(RsstreemEnv::parse_case_body)
            .skip(self.reserved("case"))
            .and(self.parser(RsstreemEnv::parse_cparam))
            .and(self.parser(RsstreemEnv::parse_stmts))
            .map(|((b, p), s)| match p {
                     Ast::Plambda {
                         pat: p_pat,
                         cond: p_cond,
                         body: p_body,
                         next: p_next,
                     } => {
                         let boxied_cparam = Box::new(Ast::Plambda {
                                                          pat: p_pat,
                                                          cond: p_cond,
                                                          body: Box::new(s),
                                                          next: p_next,
                                                      });
                         match b {
                             Ast::Plambda {
                                 pat,
                                 cond,
                                 body,
                                 next,
                             } => {
                                 next.borrow_mut().push(boxied_cparam);

                                 Ast::Plambda {
                                     pat: pat,
                                     cond: cond,
                                     body: body,
                                     next: next,
                                 }
                             }
                             _ => panic!("not match case_body"),
                         }
                     }

                     _ => panic!("not match case_params"),
                 });

        top_case_stmt.or(seaq_case_stmt).parse_stream(input)
    }

    fn parse_block(&self, input: I) -> ParseResult<Ast, I> {
        let normal_blk = self.parser(RsstreemEnv::parse_stmts)
            .map(|s| {
                     Ast::Lambda {
                         args: Box::new(Ast::Null),
                         body: Box::new(s),
                         block: 1,
                     }
                 });

        let blk_with_param = self.parser(RsstreemEnv::parse_bparam)
            .and(self.parser(RsstreemEnv::parse_stmts))
            .map(|(b, s)| {
                     Ast::Lambda {
                         args: Box::new(b),
                         body: Box::new(s),
                         block: 0,
                     }
                 });

        let case_blk = self.parser(RsstreemEnv::parse_case_body);

        let case_else_blk = self.parser(RsstreemEnv::parse_case_body)
            .skip(self.reserved("else"))
            .skip(self.reserved_op("->"))
            .and(self.parser(RsstreemEnv::parse_stmts))
            .map(|(c, s)| {
                     Ast::Plambda {
                         pat: Box::new(Ast::Null),
                         cond: Box::new(Ast::Null),
                         body: Box::new(s),
                         next: RefCell::new(vec![Box::new(c)]),
                     }
                 });

        // FIXME: Occur type error when use `choice` or `choice!`
        self.braces(normal_blk.or(blk_with_param).or(case_blk).or(case_else_blk))
            .parse_stream(input)
    }

    fn parse_bparam(&self, input: I) -> ParseResult<Ast, I> {
        self.reserved_op("->")
            .map(|_| Ast::Null)
            .or(self.parser(RsstreemEnv::parse_f_args)
                    .skip(self.reserved_op("->")))
            .parse_stream(input)
    }

    fn parse_opt_f_args(&self, input: I) -> ParseResult<Ast, I> {
        sep_by::<Vec<Box<Ast>>, _, _>(self.parser(RsstreemEnv::parse_var).map(|v| Box::new(v)),
                                      token(','))
                .map(|v| Ast::Args { data: v })
                .parse_stream(input)
    }

    fn parse_f_args(&self, input: I) -> ParseResult<Ast, I> {
        sep_by1::<Vec<Box<Ast>>, _, _>(self.parser(RsstreemEnv::parse_var).map(|v| Box::new(v)),
                                       token(','))
                .map(|v| Ast::Args { data: v })
                .parse_stream(input)
    }

    fn parse_opt_terms(&self, input: I) -> ParseResult<(), I> {
        skip_many(token(';').or(token('\n'))).parse_stream(input)
    }

    fn parse_terms(&self, input: I) -> ParseResult<(), I> {
        skip_many1(token(';').or(token('\n'))).parse_stream(input)
    }

    // fn parse_term(&self, input: I) -> ParseResult<(), I> {
    //     skip_many().parse_stream(input)
    // }
}

pub fn parse_code<'a>(code: &'a str) -> Result<Vec<Ast>, ParseError<&'a str>> {
    let streem_env =
        LanguageEnv::new(LanguageDef {
                             ident: Identifier {
                                 start: letter(),
                                 rest: alpha_num(),
                                 reserved: ["if",
                                            "else",
                                            "skip",
                                            "case",
                                            "emif",
                                            "return",
                                            "namespace",
                                            "class",
                                            "import",
                                            "def",
                                            "method",
                                            "new",
                                            "nil",
                                            "true",
                                            "false"]
                                         .iter()
                                         .map(|x| (*x).into())
                                         .collect(),
                             },
                             op: Identifier {
                                 start: satisfy(|c| "+-*/%=!<>&|)(:".chars().any(|x| x == c)),
                                 rest: satisfy(|c| "+-*/%=!<>&|)(:".chars().any(|x| x == c)),
                                 reserved: ["::", ":", "==", "=", "(", ")", "+", "->", "*", "/",
                                            "%", "!=", "<=", ">=", "<-", "->", ">", "<", "&&", "&"]
                                         .iter()
                                         .map(|x| (*x).into())
                                         .collect(),
                             },
                             comment_start: string("/*").map(|_| ()),
                             comment_end: string("*/").map(|_| ()),
                             comment_line: string("//").map(|_| ()),
                         });

    let env = RsstreemEnv { env: streem_env };

    env.white_space()
        .with(many1::<Vec<Ast>, _>(env.add()))
        .parse(code)
        .map(|(e, _)| e)
}
<|endoftext|>


<commit_before>use super::parse_module;

use core::semantic::ast::Node;

macro_rules! expr_test {
    ($name:ident, $code:expr) => {
        #[test]
        fn $name() {
            assert_eq!( parse_module($code)
                            .unwrap()[0]
                            .to_sexpr(0)
                      , $code)
        }
    }
}

expr_test!(test_basic_add, "(+ 1 2)");
expr_test!(test_basic_sub, "(- 3 4)");
expr_test!(test_basic_div, "(/ 5 6)");
expr_test!(test_basic_mul, "(* 1 2)");
expr_test!(test_nested_arith_1, "(+ 1 (- 2 3))");
expr_test!(test_nested_arith_2, "(* (+ 1 2) 3 4)");
expr_test!(test_nested_arith_3, "(+ (/ 1 2) (* 3 4))");
expr_test!(test_call_1, "(my_fn 1 2)");
expr_test!(test_call_2, "(my_fn (my_other_fn a_var a_different_var))");
expr_test!(test_call_3,
    "(my_fn (my_other_fn a_var a_different_var) VarWithUppercase Othervar)");
expr_test!(test_call_4, "(my_fn (my_other_fn a_var a_different_var) (another_fn a_var))");
<commit_msg>Add parser tests for calls involving pointers<commit_after>use super::parse_module;

use core::semantic::ast::Node;

macro_rules! expr_test {
    ($name:ident, $code:expr) => {
        #[test]
        fn $name() {
            assert_eq!( parse_module($code)
                            .unwrap()[0]
                            .to_sexpr(0)
                      , $code)
        }
    }
}

expr_test!(test_basic_add, "(+ 1 2)");
expr_test!(test_basic_sub, "(- 3 4)");
expr_test!(test_basic_div, "(/ 5 6)");
expr_test!(test_basic_mul, "(* 1 2)");
expr_test!(test_nested_arith_1, "(+ 1 (- 2 3))");
expr_test!(test_nested_arith_2, "(* (+ 1 2) 3 4)");
expr_test!(test_nested_arith_3, "(+ (/ 1 2) (* 3 4))");

expr_test!(test_call_1, "(my_fn 1 2)");
expr_test!(test_call_2, "(my_fn (my_other_fn a_var a_different_var))");
expr_test!(test_call_3,
    "(my_fn (my_other_fn a_var a_different_var) VarWithUppercase Othervar)");
expr_test!(test_call_4, "(my_fn (my_other_fn a_var a_different_var) (another_fn a_var))");

expr_test!(test_call_ptr_1, "(my_fn a *b)");
expr_test!(test_call_ptr_2, "(my_fn *a *b)");
expr_test!(test_call_ptr_3, "(my_fn &a)");
expr_test!(test_call_ptr_4, "(my_fn a &b)");
expr_test!(test_call_ptr_5, "(my_fn &a &b)");
expr_test!(test_call_ptr_6, "(my_fn @a)");
expr_test!(test_call_ptr_7, "(my_fn a @b)");
expr_test!(test_call_ptr_8, "(my_fn @a @b)");
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Gamma and derived distributions.

use core::fmt;

use self::GammaRepr::*;
use self::ChiSquaredRepr::*;

#[cfg(not(test))] // only necessary for no_std
use FloatMath;

use {Open01, Rng};
use super::normal::StandardNormal;
use super::{Exp, IndependentSample, Sample};

/// The Gamma distribution `Gamma(shape, scale)` distribution.
///
/// The density function of this distribution is
///
/// ```text
/// f(x) =  x^(k - 1) * exp(-x / θ) / (Γ(k) * θ^k)
/// ```
///
/// where `Γ` is the Gamma function, `k` is the shape and `θ` is the
/// scale and both `k` and `θ` are strictly positive.
///
/// The algorithm used is that described by Marsaglia & Tsang 2000[1],
/// falling back to directly sampling from an Exponential for `shape
/// == 1`, and using the boosting technique described in [1] for
/// `shape < 1`.
///
/// [1]: George Marsaglia and Wai Wan Tsang. 2000. "A Simple Method
/// for Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3
/// (September 2000),
/// 363-372. DOI:[10.1145/358407.358414](http://doi.acm.org/10.1145/358407.358414)
pub struct Gamma {
    repr: GammaRepr,
}

impl fmt::Debug for Gamma {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Gamma")
         .field("repr",
                &match self.repr {
                    GammaRepr::Large(_) => "Large",
                    GammaRepr::One(_) => "Exp",
                    GammaRepr::Small(_) => "Small"
                })
          .finish()
    }
}

enum GammaRepr {
    Large(GammaLargeShape),
    One(Exp),
    Small(GammaSmallShape),
}

// These two helpers could be made public, but saving the
// match-on-Gamma-enum branch from using them directly (e.g. if one
// knows that the shape is always > 1) doesn't appear to be much
// faster.

/// Gamma distribution where the shape parameter is less than 1.
///
/// Note, samples from this require a compulsory floating-point `pow`
/// call, which makes it significantly slower than sampling from a
/// gamma distribution where the shape parameter is greater than or
/// equal to 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaSmallShape {
    inv_shape: f64,
    large_shape: GammaLargeShape,
}

/// Gamma distribution where the shape parameter is larger than 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaLargeShape {
    scale: f64,
    c: f64,
    d: f64,
}

impl Gamma {
    /// Construct an object representing the `Gamma(shape, scale)`
    /// distribution.
    ///
    /// Panics if `shape <= 0` or `scale <= 0`.
    pub fn new(shape: f64, scale: f64) -> Gamma {
        assert!(shape > 0.0, "Gamma::new called with shape <= 0");
        assert!(scale > 0.0, "Gamma::new called with scale <= 0");

        let repr = match shape {
            1.0 => One(Exp::new(1.0 / scale)),
            0.0...1.0 => Small(GammaSmallShape::new_raw(shape, scale)),
            _ => Large(GammaLargeShape::new_raw(shape, scale)),
        };
        Gamma { repr: repr }
    }
}

impl GammaSmallShape {
    fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
        GammaSmallShape {
            inv_shape: 1. / shape,
            large_shape: GammaLargeShape::new_raw(shape + 1.0, scale),
        }
    }
}

impl GammaLargeShape {
    fn new_raw(shape: f64, scale: f64) -> GammaLargeShape {
        let d = shape - 1. / 3.;
        GammaLargeShape {
            scale: scale,
            c: 1. / (9. * d).sqrt(),
            d: d,
        }
    }
}

impl Sample<f64> for Gamma {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
        self.ind_sample(rng)
    }
}
impl Sample<f64> for GammaSmallShape {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
        self.ind_sample(rng)
    }
}
impl Sample<f64> for GammaLargeShape {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
        self.ind_sample(rng)
    }
}

impl IndependentSample<f64> for Gamma {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        match self.repr {
            Small(ref g) => g.ind_sample(rng),
            One(ref g) => g.ind_sample(rng),
            Large(ref g) => g.ind_sample(rng),
        }
    }
}
impl IndependentSample<f64> for GammaSmallShape {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let Open01(u) = rng.gen::<Open01<f64>>();

        self.large_shape.ind_sample(rng) * u.powf(self.inv_shape)
    }
}
impl IndependentSample<f64> for GammaLargeShape {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        loop {
            let StandardNormal(x) = rng.gen::<StandardNormal>();
            let v_cbrt = 1.0 + self.c * x;
            if v_cbrt <= 0.0 {
                // a^3 <= 0 iff a <= 0
                continue;
            }

            let v = v_cbrt * v_cbrt * v_cbrt;
            let Open01(u) = rng.gen::<Open01<f64>>();

            let x_sqr = x * x;
            if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
               u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
                return self.d * v * self.scale;
            }
        }
    }
}

/// The chi-squared distribution `χ²(k)`, where `k` is the degrees of
/// freedom.
///
/// For `k > 0` integral, this distribution is the sum of the squares
/// of `k` independent standard normal random variables. For other
/// `k`, this uses the equivalent characterization `χ²(k) = Gamma(k/2,
/// 2)`.
pub struct ChiSquared {
    repr: ChiSquaredRepr,
}

impl fmt::Debug for ChiSquared {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("ChiSquared")
         .field("repr",
                &match self.repr {
                    ChiSquaredRepr::DoFExactlyOne => "DoFExactlyOne",
                    ChiSquaredRepr::DoFAnythingElse(_) => "DoFAnythingElse",
                })
         .finish()
    }
}

enum ChiSquaredRepr {
    // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1,
    // e.g. when alpha = 1/2 as it would be for this case, so special-
    // casing and using the definition of N(0,1)^2 is faster.
    DoFExactlyOne,
    DoFAnythingElse(Gamma),
}

impl ChiSquared {
    /// Create a new chi-squared distribution with degrees-of-freedom
    /// `k`. Panics if `k < 0`.
    pub fn new(k: f64) -> ChiSquared {
        let repr = if k == 1.0 {
            DoFExactlyOne
        } else {
            assert!(k > 0.0, "ChiSquared::new called with `k` < 0");
            DoFAnythingElse(Gamma::new(0.5 * k, 2.0))
        };
        ChiSquared { repr: repr }
    }
}

impl Sample<f64> for ChiSquared {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
        self.ind_sample(rng)
    }
}

impl IndependentSample<f64> for ChiSquared {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        match self.repr {
            DoFExactlyOne => {
                // k == 1 => N(0,1)^2
                let StandardNormal(norm) = rng.gen::<StandardNormal>();
                norm * norm
            }
            DoFAnythingElse(ref g) => g.ind_sample(rng),
        }
    }
}

/// The Fisher F distribution `F(m, n)`.
///
/// This distribution is equivalent to the ratio of two normalised
/// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) /
/// (χ²(n)/n)`.
pub struct FisherF {
    numer: ChiSquared,
    denom: ChiSquared,
    // denom_dof / numer_dof so that this can just be a straight
    // multiplication, rather than a division.
    dof_ratio: f64,
}

impl FisherF {
    /// Create a new `FisherF` distribution, with the given
    /// parameter. Panics if either `m` or `n` are not positive.
    pub fn new(m: f64, n: f64) -> FisherF {
        assert!(m > 0.0, "FisherF::new called with `m < 0`");
        assert!(n > 0.0, "FisherF::new called with `n < 0`");

        FisherF {
            numer: ChiSquared::new(m),
            denom: ChiSquared::new(n),
            dof_ratio: n / m,
        }
    }
}

impl Sample<f64> for FisherF {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
        self.ind_sample(rng)
    }
}

impl IndependentSample<f64> for FisherF {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        self.numer.ind_sample(rng) / self.denom.ind_sample(rng) * self.dof_ratio
    }
}

impl fmt::Debug for FisherF {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("FisherF")
         .field("numer", &self.numer)
         .field("denom", &self.denom)
         .field("dof_ratio", &self.dof_ratio)
         .finish()
    }
}

/// The Student t distribution, `t(nu)`, where `nu` is the degrees of
/// freedom.
pub struct StudentT {
    chi: ChiSquared,
    dof: f64,
}

impl StudentT {
    /// Create a new Student t distribution with `n` degrees of
    /// freedom. Panics if `n <= 0`.
    pub fn new(n: f64) -> StudentT {
        assert!(n > 0.0, "StudentT::new called with `n <= 0`");
        StudentT {
            chi: ChiSquared::new(n),
            dof: n,
        }
    }
}

impl Sample<f64> for StudentT {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
        self.ind_sample(rng)
    }
}

impl IndependentSample<f64> for StudentT {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let StandardNormal(norm) = rng.gen::<StandardNormal>();
        norm * (self.dof / self.chi.ind_sample(rng)).sqrt()
    }
}

impl fmt::Debug for StudentT {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("StudentT")
         .field("chi", &self.chi)
         .field("dof", &self.dof)
         .finish()
    }
}

#[cfg(test)]
mod tests {
    use distributions::{IndependentSample, Sample};
    use super::{ChiSquared, FisherF, StudentT};

    #[test]
    fn test_chi_squared_one() {
        let mut chi = ChiSquared::new(1.0);
        let mut rng = ::test::rng();
        for _ in 0..1000 {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_small() {
        let mut chi = ChiSquared::new(0.5);
        let mut rng = ::test::rng();
        for _ in 0..1000 {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_large() {
        let mut chi = ChiSquared::new(30.0);
        let mut rng = ::test::rng();
        for _ in 0..1000 {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    #[should_panic]
    fn test_chi_squared_invalid_dof() {
        ChiSquared::new(-1.0);
    }

    #[test]
    fn test_f() {
        let mut f = FisherF::new(2.0, 32.0);
        let mut rng = ::test::rng();
        for _ in 0..1000 {
            f.sample(&mut rng);
            f.ind_sample(&mut rng);
        }
    }

    #[test]
    fn test_t() {
        let mut t = StudentT::new(11.0);
        let mut rng = ::test::rng();
        for _ in 0..1000 {
            t.sample(&mut rng);
            t.ind_sample(&mut rng);
        }
    }
}

#[cfg(test)]
mod bench {
    extern crate test;
    use self::test::Bencher;
    use std::mem::size_of;
    use distributions::IndependentSample;
    use super::Gamma;

    #[bench]
    fn bench_gamma_large_shape(b: &mut Bencher) {
        let gamma = Gamma::new(10., 1.0);
        let mut rng = ::test::weak_rng();

        b.iter(|| {
            for _ in 0..::RAND_BENCH_N {
                gamma.ind_sample(&mut rng);
            }
        });
        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
    }

    #[bench]
    fn bench_gamma_small_shape(b: &mut Bencher) {
        let gamma = Gamma::new(0.1, 1.0);
        let mut rng = ::test::weak_rng();

        b.iter(|| {
            for _ in 0..::RAND_BENCH_N {
                gamma.ind_sample(&mut rng);
            }
        });
        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
    }
}
<commit_msg>Avoid to use floating point match<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Gamma and derived distributions.

use core::fmt;

use self::GammaRepr::*;
use self::ChiSquaredRepr::*;

#[cfg(not(test))] // only necessary for no_std
use FloatMath;

use {Open01, Rng};
use super::normal::StandardNormal;
use super::{Exp, IndependentSample, Sample};

/// The Gamma distribution `Gamma(shape, scale)` distribution.
///
/// The density function of this distribution is
///
/// ```text
/// f(x) =  x^(k - 1) * exp(-x / θ) / (Γ(k) * θ^k)
/// ```
///
/// where `Γ` is the Gamma function, `k` is the shape and `θ` is the
/// scale and both `k` and `θ` are strictly positive.
///
/// The algorithm used is that described by Marsaglia & Tsang 2000[1],
/// falling back to directly sampling from an Exponential for `shape
/// == 1`, and using the boosting technique described in [1] for
/// `shape < 1`.
///
/// [1]: George Marsaglia and Wai Wan Tsang. 2000. "A Simple Method
/// for Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3
/// (September 2000),
/// 363-372. DOI:[10.1145/358407.358414](http://doi.acm.org/10.1145/358407.358414)
pub struct Gamma {
    repr: GammaRepr,
}

impl fmt::Debug for Gamma {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Gamma")
         .field("repr",
                &match self.repr {
                    GammaRepr::Large(_) => "Large",
                    GammaRepr::One(_) => "Exp",
                    GammaRepr::Small(_) => "Small"
                })
          .finish()
    }
}

enum GammaRepr {
    Large(GammaLargeShape),
    One(Exp),
    Small(GammaSmallShape),
}

// These two helpers could be made public, but saving the
// match-on-Gamma-enum branch from using them directly (e.g. if one
// knows that the shape is always > 1) doesn't appear to be much
// faster.

/// Gamma distribution where the shape parameter is less than 1.
///
/// Note, samples from this require a compulsory floating-point `pow`
/// call, which makes it significantly slower than sampling from a
/// gamma distribution where the shape parameter is greater than or
/// equal to 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaSmallShape {
    inv_shape: f64,
    large_shape: GammaLargeShape,
}

/// Gamma distribution where the shape parameter is larger than 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaLargeShape {
    scale: f64,
    c: f64,
    d: f64,
}

impl Gamma {
    /// Construct an object representing the `Gamma(shape, scale)`
    /// distribution.
    ///
    /// Panics if `shape <= 0` or `scale <= 0`.
    pub fn new(shape: f64, scale: f64) -> Gamma {
        assert!(shape > 0.0, "Gamma::new called with shape <= 0");
        assert!(scale > 0.0, "Gamma::new called with scale <= 0");

        let repr = if shape == 1.0 {
            One(Exp::new(1.0 / scale))
        } else if 0.0 <= shape && shape < 1.0 {
            Small(GammaSmallShape::new_raw(shape, scale))
        } else {
            Large(GammaLargeShape::new_raw(shape, scale))
        };
        Gamma { repr }
    }
}

impl GammaSmallShape {
    fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
        GammaSmallShape {
            inv_shape: 1. / shape,
            large_shape: GammaLargeShape::new_raw(shape + 1.0, scale),
        }
    }
}

impl GammaLargeShape {
    fn new_raw(shape: f64, scale: f64) -> GammaLargeShape {
        let d = shape - 1. / 3.;
        GammaLargeShape {
            scale: scale,
            c: 1. / (9. * d).sqrt(),
            d: d,
        }
    }
}

impl Sample<f64> for Gamma {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
        self.ind_sample(rng)
    }
}
impl Sample<f64> for GammaSmallShape {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
        self.ind_sample(rng)
    }
}
impl Sample<f64> for GammaLargeShape {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
        self.ind_sample(rng)
    }
}

impl IndependentSample<f64> for Gamma {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        match self.repr {
            Small(ref g) => g.ind_sample(rng),
            One(ref g) => g.ind_sample(rng),
            Large(ref g) => g.ind_sample(rng),
        }
    }
}
impl IndependentSample<f64> for GammaSmallShape {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let Open01(u) = rng.gen::<Open01<f64>>();

        self.large_shape.ind_sample(rng) * u.powf(self.inv_shape)
    }
}
impl IndependentSample<f64> for GammaLargeShape {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        loop {
            let StandardNormal(x) = rng.gen::<StandardNormal>();
            let v_cbrt = 1.0 + self.c * x;
            if v_cbrt <= 0.0 {
                // a^3 <= 0 iff a <= 0
                continue;
            }

            let v = v_cbrt * v_cbrt * v_cbrt;
            let Open01(u) = rng.gen::<Open01<f64>>();

            let x_sqr = x * x;
            if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
               u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
                return self.d * v * self.scale;
            }
        }
    }
}

/// The chi-squared distribution `χ²(k)`, where `k` is the degrees of
/// freedom.
///
/// For `k > 0` integral, this distribution is the sum of the squares
/// of `k` independent standard normal random variables. For other
/// `k`, this uses the equivalent characterization `χ²(k) = Gamma(k/2,
/// 2)`.
pub struct ChiSquared {
    repr: ChiSquaredRepr,
}

impl fmt::Debug for ChiSquared {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("ChiSquared")
         .field("repr",
                &match self.repr {
                    ChiSquaredRepr::DoFExactlyOne => "DoFExactlyOne",
                    ChiSquaredRepr::DoFAnythingElse(_) => "DoFAnythingElse",
                })
         .finish()
    }
}

enum ChiSquaredRepr {
    // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1,
    // e.g. when alpha = 1/2 as it would be for this case, so special-
    // casing and using the definition of N(0,1)^2 is faster.
    DoFExactlyOne,
    DoFAnythingElse(Gamma),
}

impl ChiSquared {
    /// Create a new chi-squared distribution with degrees-of-freedom
    /// `k`. Panics if `k < 0`.
    pub fn new(k: f64) -> ChiSquared {
        let repr = if k == 1.0 {
            DoFExactlyOne
        } else {
            assert!(k > 0.0, "ChiSquared::new called with `k` < 0");
            DoFAnythingElse(Gamma::new(0.5 * k, 2.0))
        };
        ChiSquared { repr: repr }
    }
}

impl Sample<f64> for ChiSquared {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
        self.ind_sample(rng)
    }
}

impl IndependentSample<f64> for ChiSquared {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        match self.repr {
            DoFExactlyOne => {
                // k == 1 => N(0,1)^2
                let StandardNormal(norm) = rng.gen::<StandardNormal>();
                norm * norm
            }
            DoFAnythingElse(ref g) => g.ind_sample(rng),
        }
    }
}

/// The Fisher F distribution `F(m, n)`.
///
/// This distribution is equivalent to the ratio of two normalised
/// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) /
/// (χ²(n)/n)`.
pub struct FisherF {
    numer: ChiSquared,
    denom: ChiSquared,
    // denom_dof / numer_dof so that this can just be a straight
    // multiplication, rather than a division.
    dof_ratio: f64,
}

impl FisherF {
    /// Create a new `FisherF` distribution, with the given
    /// parameter. Panics if either `m` or `n` are not positive.
    pub fn new(m: f64, n: f64) -> FisherF {
        assert!(m > 0.0, "FisherF::new called with `m < 0`");
        assert!(n > 0.0, "FisherF::new called with `n < 0`");

        FisherF {
            numer: ChiSquared::new(m),
            denom: ChiSquared::new(n),
            dof_ratio: n / m,
        }
    }
}

impl Sample<f64> for FisherF {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
        self.ind_sample(rng)
    }
}

impl IndependentSample<f64> for FisherF {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        self.numer.ind_sample(rng) / self.denom.ind_sample(rng) * self.dof_ratio
    }
}

impl fmt::Debug for FisherF {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("FisherF")
         .field("numer", &self.numer)
         .field("denom", &self.denom)
         .field("dof_ratio", &self.dof_ratio)
         .finish()
    }
}

/// The Student t distribution, `t(nu)`, where `nu` is the degrees of
/// freedom.
pub struct StudentT {
    chi: ChiSquared,
    dof: f64,
}

impl StudentT {
    /// Create a new Student t distribution with `n` degrees of
    /// freedom. Panics if `n <= 0`.
    pub fn new(n: f64) -> StudentT {
        assert!(n > 0.0, "StudentT::new called with `n <= 0`");
        StudentT {
            chi: ChiSquared::new(n),
            dof: n,
        }
    }
}

impl Sample<f64> for StudentT {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
        self.ind_sample(rng)
    }
}

impl IndependentSample<f64> for StudentT {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let StandardNormal(norm) = rng.gen::<StandardNormal>();
        norm * (self.dof / self.chi.ind_sample(rng)).sqrt()
    }
}

impl fmt::Debug for StudentT {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("StudentT")
         .field("chi", &self.chi)
         .field("dof", &self.dof)
         .finish()
    }
}

#[cfg(test)]
mod tests {
    use distributions::{IndependentSample, Sample};
    use super::{ChiSquared, FisherF, StudentT};

    #[test]
    fn test_chi_squared_one() {
        let mut chi = ChiSquared::new(1.0);
        let mut rng = ::test::rng();
        for _ in 0..1000 {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_small() {
        let mut chi = ChiSquared::new(0.5);
        let mut rng = ::test::rng();
        for _ in 0..1000 {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_large() {
        let mut chi = ChiSquared::new(30.0);
        let mut rng = ::test::rng();
        for _ in 0..1000 {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    #[should_panic]
    fn test_chi_squared_invalid_dof() {
        ChiSquared::new(-1.0);
    }

    #[test]
    fn test_f() {
        let mut f = FisherF::new(2.0, 32.0);
        let mut rng = ::test::rng();
        for _ in 0..1000 {
            f.sample(&mut rng);
            f.ind_sample(&mut rng);
        }
    }

    #[test]
    fn test_t() {
        let mut t = StudentT::new(11.0);
        let mut rng = ::test::rng();
        for _ in 0..1000 {
            t.sample(&mut rng);
            t.ind_sample(&mut rng);
        }
    }
}

#[cfg(test)]
mod bench {
    extern crate test;
    use self::test::Bencher;
    use std::mem::size_of;
    use distributions::IndependentSample;
    use super::Gamma;

    #[bench]
    fn bench_gamma_large_shape(b: &mut Bencher) {
        let gamma = Gamma::new(10., 1.0);
        let mut rng = ::test::weak_rng();

        b.iter(|| {
            for _ in 0..::RAND_BENCH_N {
                gamma.ind_sample(&mut rng);
            }
        });
        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
    }

    #[bench]
    fn bench_gamma_small_shape(b: &mut Bencher) {
        let gamma = Gamma::new(0.1, 1.0);
        let mut rng = ::test::weak_rng();

        b.iter(|| {
            for _ in 0..::RAND_BENCH_N {
                gamma.ind_sample(&mut rng);
            }
        });
        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
    }
}
<|endoftext|>


<commit_before>use escargot::CargoBuild;
use failure::ResultExt;
use std::io;
use std::{thread, time};
use varlink::Connection;
use Result;

fn run_self_test(address: String) -> Result<()> {
    let client_address = address.clone();

    let child = thread::spawn(move || {
        if let Err(e) = ::run_server(&address, 4) {
            match e.kind() {
                ::varlink::ErrorKind::Timeout => {}
                _ => panic!("error: {}", e),
            }
        }
    });

    // give server time to start
    thread::sleep(time::Duration::from_secs(1));

    let ret = ::run_client(Connection::with_address(&client_address)?);
    if let Err(e) = ret {
        panic!("error: {:?}", e);
    }
    if let Err(e) = child.join() {
        Err(io::Error::new(io::ErrorKind::ConnectionRefused, format!("{:#?}", e)).into())
    } else {
        Ok(())
    }
}

#[test]
fn test_unix() -> ::Result<()> {
    run_self_test("unix:/tmp/org.varlink.certification".into())
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn test_unix_abstract() -> Result<()> {
    run_self_test("unix:@org.varlink.certification".into())
}

#[test]
fn test_tcp() -> Result<()> {
    run_self_test("tcp:0.0.0.0:23456".into())
}

fn get_exec() -> Result<String> {
    let runner = CargoBuild::new()
        .current_release()
        .run()
        .context(::ErrorKind::Io_Error(::std::io::ErrorKind::NotFound))?;
    Ok(runner.path().to_owned().to_string_lossy().to_string())
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn test_exec() -> Result<()> {
    ::run_client(Connection::with_activate(&format!(
        "{} --varlink=$VARLINK_ADDRESS",
        get_exec()?
    ))?)
}

#[test]
fn test_wrong_address_1() {
    assert!(::run_server("tcpd:0.0.0.0:12345".into(), 1).is_err());
}
<commit_msg>varlink-certification/src/test.rs: mark get_exec() linux only<commit_after>use escargot::CargoBuild;
use failure::ResultExt;
use std::io;
use std::{thread, time};
use varlink::Connection;
use Result;

fn run_self_test(address: String) -> Result<()> {
    let client_address = address.clone();

    let child = thread::spawn(move || {
        if let Err(e) = ::run_server(&address, 4) {
            match e.kind() {
                ::varlink::ErrorKind::Timeout => {}
                _ => panic!("error: {}", e),
            }
        }
    });

    // give server time to start
    thread::sleep(time::Duration::from_secs(1));

    let ret = ::run_client(Connection::with_address(&client_address)?);
    if let Err(e) = ret {
        panic!("error: {:?}", e);
    }
    if let Err(e) = child.join() {
        Err(io::Error::new(io::ErrorKind::ConnectionRefused, format!("{:#?}", e)).into())
    } else {
        Ok(())
    }
}

#[test]
fn test_unix() -> ::Result<()> {
    run_self_test("unix:/tmp/org.varlink.certification".into())
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn test_unix_abstract() -> Result<()> {
    run_self_test("unix:@org.varlink.certification".into())
}

#[test]
fn test_tcp() -> Result<()> {
    run_self_test("tcp:0.0.0.0:23456".into())
}

#[cfg(any(target_os = "linux", target_os = "android"))]
fn get_exec() -> Result<String> {
    let runner = CargoBuild::new()
        .current_release()
        .run()
        .context(::ErrorKind::Io_Error(::std::io::ErrorKind::NotFound))?;
    Ok(runner.path().to_owned().to_string_lossy().to_string())
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn test_exec() -> Result<()> {
    ::run_client(Connection::with_activate(&format!(
        "{} --varlink=$VARLINK_ADDRESS",
        get_exec()?
    ))?)
}

#[test]
fn test_wrong_address_1() {
    assert!(::run_server("tcpd:0.0.0.0:12345".into(), 1).is_err());
}
<|endoftext|>


<commit_before>/*!
Rectangle Functions
 */

use std::mem;
use libc::c_int;

/// A structure that defines a two dimensional point.
#[deriving(PartialEq, Clone, Show)]
#[repr(C)]
pub struct Point {
    pub x: i32,
    pub y: i32
}

/// A structure that defines a rectangle, with the origin at the upper left.
#[deriving(PartialEq, Clone, Show)]
#[repr(C)]
pub struct Rect {
    pub x: i32,
    pub y: i32,
    pub w: i32,
    pub h: i32
}

#[doc(hidden)]
#[allow(non_camel_case_types)]
pub mod ll {

    use libc::c_int;
    use super::Rect;
    use super::Point;

    pub type SDL_Rect = Rect;
    pub type SDL_Point = Point;
    pub type SDL_bool = c_int;

    extern "C" {
        pub fn SDL_HasIntersection(A: *const SDL_Rect, B: *const SDL_Rect) -> SDL_bool;
        pub fn SDL_IntersectRect(A: *const SDL_Rect, B: *const SDL_Rect, result: *const SDL_Rect) -> SDL_bool;
        pub fn SDL_UnionRect(A: *const SDL_Rect, B: *const SDL_Rect, result: *const SDL_Rect);
        pub fn SDL_EnclosePoints(points: *const SDL_Point, count: c_int, clip: *const SDL_Rect, result: *const SDL_Rect) -> SDL_bool;
        pub fn SDL_IntersectRectAndLine(rect: *const SDL_Rect, X1: *const c_int, Y1: *const c_int, X2: *const c_int, Y2: *const c_int) -> SDL_bool;
    }
}

impl Point {
    pub fn new(x: i32, y: i32) -> Point {
        Point {
            x: x,
            y: y
        }
    }
}

impl Rect {
    pub fn new(x: i32, y: i32, w: i32, h: i32) -> Rect {
        Rect {
            x: x,
            y: y,
            w: w,
            h: h
        }
    }

    /// Calculate a minimal rectangle enclosing a set of points.
    pub fn from_enclose_points(points: &[Point], clip: Option<Rect>) -> Option<Rect> {
        let out: Rect = Rect::new(0, 0, 0, 0);

        let result = unsafe {
            ll::SDL_EnclosePoints(
                mem::transmute(points.as_ptr()),
                points.len() as c_int,
                mem::transmute(clip.as_ref()),
                &out
            ) != 0
        };

        if result {
            Some(out)
        } else {
            None
        }
    }

    /// Check whether a rectangle has no area.
    pub fn is_empty(&self) -> bool {
        (self.w <= 0) || (self.h <= 0)
    }

    /// Determine whether two rectangles intersect.
    pub fn has_intersection(&self, other: &Rect) -> bool {
        unsafe {
            ll::SDL_HasIntersection(self, other) != 0
        }
    }

    /// Calculate the intersection of two rectangles.
    pub fn intersection(&self, other: &Rect) -> Option<Rect> {
        let out: Rect = Rect::new(0, 0, 0, 0);

        let result = unsafe {
            ll::SDL_IntersectRect(self, other, &out) != 0
        };

        if result {
            Some(out)
        } else {
            None
        }
    }

    /// Calculate the union of two rectangles.
    pub fn union(&self, other: &Rect) -> Rect {
        let out: Rect = Rect::new(0, 0, 0, 0);

        unsafe {
            ll::SDL_UnionRect(self, other, &out)
        };

        out
    }

    /// Calculate the intersection of a rectangle and line segment. return points of intersection.
    pub fn intersect_line(&self, start: &Point, end: &Point) -> Option<(Point, Point)> {
        let out_start: Point = start.clone();
        let out_end: Point = end.clone();

        let result = unsafe {
            ll::SDL_IntersectRectAndLine(self, &out_start.x, &out_start.y, &out_end.x, &out_end.y) != 0
        };

        if result {
            Some((out_start, out_end))
        } else {
            None
        }
    }
}

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

    #[test]
    fn test_from_enclose_points() {
        assert_eq!(Rect::from_enclose_points(&[Point::new(2, 4), Point::new(5,9)], None),
                   Some(Rect::new(2, 4, 4, 6)));
        assert!(Rect::from_enclose_points(&[Point::new(0, 0), Point::new(10,10)],
                                          Some(Rect::new(3, 3, 1, 1))).is_none());
    }

    #[test]
    fn test_has_intersection() {
        assert!(Rect::new(0, 0, 10, 10).has_intersection(&Rect::new(9, 9, 10, 10)));
        // edge
        assert!(! Rect::new(0, 0, 10, 10).has_intersection(&Rect::new(10, 10, 10, 10)));
        // out
        assert!(! Rect::new(0, 0, 10, 10).has_intersection(&Rect::new(11, 11, 10, 10)));
    }

    #[test]
    fn test_intersection() {
        assert_eq!(Rect::new(0, 0, 10, 10).intersection(&Rect::new(9, 9, 10, 10)),
                   Some(Rect::new(9, 9, 1, 1)));
        assert!(Rect::new(0, 0, 10, 10).intersection(&Rect::new(11, 11, 10, 10)).is_none());
    }

    #[test]
    fn test_union() {
        assert_eq!(Rect::new(0, 0, 1, 1).union(&Rect::new(9, 9, 1, 1)),
                   Rect::new(0, 0, 10, 10));
    }

    #[test]
    fn test_intersect_line() {
        assert_eq!(Rect::new(1, 1, 5, 5).intersect_line(&Point::new(0, 0), &Point::new(10, 10)),
                   Some((Point::new(1, 1), Point::new(5, 5))));
    }
 }
<commit_msg>remove glob using in response to compiler change<commit_after>/*!
Rectangle Functions
 */

use std::mem;
use libc::c_int;

/// A structure that defines a two dimensional point.
#[deriving(PartialEq, Clone, Show)]
#[repr(C)]
pub struct Point {
    pub x: i32,
    pub y: i32
}

/// A structure that defines a rectangle, with the origin at the upper left.
#[deriving(PartialEq, Clone, Show)]
#[repr(C)]
pub struct Rect {
    pub x: i32,
    pub y: i32,
    pub w: i32,
    pub h: i32
}

#[doc(hidden)]
#[allow(non_camel_case_types)]
pub mod ll {

    use libc::c_int;
    use super::Rect;
    use super::Point;

    pub type SDL_Rect = Rect;
    pub type SDL_Point = Point;
    pub type SDL_bool = c_int;

    extern "C" {
        pub fn SDL_HasIntersection(A: *const SDL_Rect, B: *const SDL_Rect) -> SDL_bool;
        pub fn SDL_IntersectRect(A: *const SDL_Rect, B: *const SDL_Rect, result: *const SDL_Rect) -> SDL_bool;
        pub fn SDL_UnionRect(A: *const SDL_Rect, B: *const SDL_Rect, result: *const SDL_Rect);
        pub fn SDL_EnclosePoints(points: *const SDL_Point, count: c_int, clip: *const SDL_Rect, result: *const SDL_Rect) -> SDL_bool;
        pub fn SDL_IntersectRectAndLine(rect: *const SDL_Rect, X1: *const c_int, Y1: *const c_int, X2: *const c_int, Y2: *const c_int) -> SDL_bool;
    }
}

impl Point {
    pub fn new(x: i32, y: i32) -> Point {
        Point {
            x: x,
            y: y
        }
    }
}

impl Rect {
    pub fn new(x: i32, y: i32, w: i32, h: i32) -> Rect {
        Rect {
            x: x,
            y: y,
            w: w,
            h: h
        }
    }

    /// Calculate a minimal rectangle enclosing a set of points.
    pub fn from_enclose_points(points: &[Point], clip: Option<Rect>) -> Option<Rect> {
        let out: Rect = Rect::new(0, 0, 0, 0);

        let result = unsafe {
            ll::SDL_EnclosePoints(
                mem::transmute(points.as_ptr()),
                points.len() as c_int,
                mem::transmute(clip.as_ref()),
                &out
            ) != 0
        };

        if result {
            Some(out)
        } else {
            None
        }
    }

    /// Check whether a rectangle has no area.
    pub fn is_empty(&self) -> bool {
        (self.w <= 0) || (self.h <= 0)
    }

    /// Determine whether two rectangles intersect.
    pub fn has_intersection(&self, other: &Rect) -> bool {
        unsafe {
            ll::SDL_HasIntersection(self, other) != 0
        }
    }

    /// Calculate the intersection of two rectangles.
    pub fn intersection(&self, other: &Rect) -> Option<Rect> {
        let out: Rect = Rect::new(0, 0, 0, 0);

        let result = unsafe {
            ll::SDL_IntersectRect(self, other, &out) != 0
        };

        if result {
            Some(out)
        } else {
            None
        }
    }

    /// Calculate the union of two rectangles.
    pub fn union(&self, other: &Rect) -> Rect {
        let out: Rect = Rect::new(0, 0, 0, 0);

        unsafe {
            ll::SDL_UnionRect(self, other, &out)
        };

        out
    }

    /// Calculate the intersection of a rectangle and line segment. return points of intersection.
    pub fn intersect_line(&self, start: &Point, end: &Point) -> Option<(Point, Point)> {
        let out_start: Point = start.clone();
        let out_end: Point = end.clone();

        let result = unsafe {
            ll::SDL_IntersectRectAndLine(self, &out_start.x, &out_start.y, &out_end.x, &out_end.y) != 0
        };

        if result {
            Some((out_start, out_end))
        } else {
            None
        }
    }
}

#[cfg(test)]
mod test {
    //use super::*;
    use super::{Rect, Point};

    #[test]
    fn test_from_enclose_points() {
        assert_eq!(Rect::from_enclose_points(&[Point::new(2, 4), Point::new(5,9)], None),
                   Some(Rect::new(2, 4, 4, 6)));
        assert!(Rect::from_enclose_points(&[Point::new(0, 0), Point::new(10,10)],
                                          Some(Rect::new(3, 3, 1, 1))).is_none());
    }

    #[test]
    fn test_has_intersection() {
        assert!(Rect::new(0, 0, 10, 10).has_intersection(&Rect::new(9, 9, 10, 10)));
        // edge
        assert!(! Rect::new(0, 0, 10, 10).has_intersection(&Rect::new(10, 10, 10, 10)));
        // out
        assert!(! Rect::new(0, 0, 10, 10).has_intersection(&Rect::new(11, 11, 10, 10)));
    }

    #[test]
    fn test_intersection() {
        assert_eq!(Rect::new(0, 0, 10, 10).intersection(&Rect::new(9, 9, 10, 10)),
                   Some(Rect::new(9, 9, 1, 1)));
        assert!(Rect::new(0, 0, 10, 10).intersection(&Rect::new(11, 11, 10, 10)).is_none());
    }

    #[test]
    fn test_union() {
        assert_eq!(Rect::new(0, 0, 1, 1).union(&Rect::new(9, 9, 1, 1)),
                   Rect::new(0, 0, 10, 10));
    }

    #[test]
    fn test_intersect_line() {
        assert_eq!(Rect::new(1, 1, 5, 5).intersect_line(&Point::new(0, 0), &Point::new(10, 10)),
                   Some((Point::new(1, 1), Point::new(5, 5))));
    }
 }
<|endoftext|>


<commit_before>pub mod sentiment {
    use std::collections::HashMap;
    use std::fs::File;
    use std::io::prelude::*;
    use std::io::{self, BufReader};
    use std::path::Path;

    pub struct Analizer {
        wordlist: HashMap<String, i8>
    }

    impl Analizer {
        pub fn analyze(self, s: &str) -> f32 {
            return 0.0;
        }
    }

    pub fn new(path: String) -> Analizer {
        let mut wordlist = HashMap::new();

        let mut f = match File::open(&path) {
            Err(why) => panic!("couldn't open {}: {}", path, why),
            Ok(f) => f,
        };

        let f = BufReader::new(f);

        for line in f.lines() {
            let l = line.unwrap();
            let parts = l.split("\t").collect::<Vec<&str>>();

            let word = parts[0].to_string();
            let score = parts[1].parse::<i8>().unwrap();

            wordlist.insert(word, score);
        }

        println!("{:?}", wordlist);
        return Analizer {
            wordlist: wordlist
        }
    }
}

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

    #[test]
    fn sentiment_test() {
        /*
           analyze("I am happy"); //Score: 3, Comparative: 1
           analyze("I am so happy"); //Score: 6, Comparative: 1.5
           analyze("I am extremely happy"); //Score: 12, Comparative: 3
           analyze("I am really sad"); //Score: -4, Comparative: -1
*/
        let mut analizer = sentiment::new("/Users/coornail/rust/ircbot/src/wordlist.txt".to_string());
        assert!(analizer.analyze("Hey you worthless scumbag") == -1.5)
    }
}
<commit_msg>Add sentiment score analysis<commit_after>pub mod sentiment {
    use std::collections::HashMap;
    use std::fs::File;
    use std::io::prelude::*;
    use std::io::{self, BufReader};
    use std::path::Path;

    pub struct Analizer {
        wordlist: HashMap<String, i8>
    }

    impl Analizer {
        pub fn analyze(self, s: &str) -> f32 {
            let tokens = s.split(" ");
            let word_count = tokens.clone().count();

            let score = tokens
                .map(|word| word.to_string().to_lowercase())
                .map(|word| match self.wordlist.get(&word) {
                    Some(word_score) => *word_score,
                    None => 0 as i8,
                })
                .fold(0, |sum, curr| sum+curr );

            return score as f32 / word_count as f32;
        }
    }

    pub fn new(path: String) -> Analizer {
        let mut wordlist = HashMap::new();

        let mut f = match File::open(&path) {
            Err(why) => panic!("couldn't open {}: {}", path, why),
            Ok(f) => f,
        };

        let f = BufReader::new(f);

        for line in f.lines() {
            let l = line.unwrap();
            let parts = l.split("\t").collect::<Vec<&str>>();

            let word = parts[0].to_string();
            let score = parts[1].parse::<i8>().unwrap();

            wordlist.insert(word, score);
        }

        return Analizer {
            wordlist: wordlist
        }
    }
}

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

    #[test]
    fn sentiment_test() {
        /*
           analyze("I am happy"); //Score: 3, Comparative: 1
           analyze("I am so happy"); //Score: 6, Comparative: 1.5
           analyze("I am extremely happy"); //Score: 12, Comparative: 3
           analyze("I am really sad"); //Score: -4, Comparative: -1
*/
        let mut analizer = sentiment::new("/Users/coornail/rust/ircbot/src/wordlist.txt".to_string());
        assert!(analizer.analyze("Hey you worthless scumbag") == -1.5)
    }
}
<|endoftext|>


<commit_before>use std::{
    env,
    fs::File,
    io,
    path::{Path, PathBuf},
};

use anyhow::Result;
use flate2::{write::GzEncoder, Compression};
use xshell::{cmd, mkdir_p, pushd, pushenv, read_file, rm_rf, write_file};

use crate::{date_iso, flags, project_root};

impl flags::Dist {
    pub(crate) fn run(self) -> Result<()> {
        let stable =
            std::env::var("GITHUB_REF").unwrap_or_default().as_str() == "refs/heads/release";

        let dist = project_root().join("dist");
        rm_rf(&dist)?;
        mkdir_p(&dist)?;

        if let Some(patch_version) = self.client_patch_version {
            let version = if stable {
                format!("0.2.{}", patch_version)
            } else {
                // A hack to make VS Code prefer nightly over stable.
                format!("0.3.{}", patch_version)
            };
            let release_tag = if stable { date_iso()? } else { "nightly".to_string() };
            dist_client(&version, &release_tag)?;
        }
        let release_channel = if stable { "stable" } else { "nightly" };
        dist_server(release_channel)?;
        Ok(())
    }
}

fn dist_client(version: &str, release_tag: &str) -> Result<()> {
    let _d = pushd("./editors/code")?;
    let nightly = release_tag == "nightly";

    let mut patch = Patch::new("./package.json")?;

    patch
        .replace(r#""version": "0.4.0-dev""#, &format!(r#""version": "{}""#, version))
        .replace(r#""releaseTag": null"#, &format!(r#""releaseTag": "{}""#, release_tag))
        .replace(r#""$generated-start": false,"#, "")
        .replace(",\n                \"$generated-end\": false", "");

    if nightly {
        patch.replace(
            r#""displayName": "rust-analyzer""#,
            r#""displayName": "rust-analyzer (nightly)""#,
        );
    }
    if !nightly {
        patch.replace(r#""enableProposedApi": true,"#, r#""#);
    }
    patch.commit()?;

    cmd!("npm ci").run()?;
    cmd!("npx vsce package -o ../../dist/rust-analyzer.vsix").run()?;
    Ok(())
}

fn dist_server(release_channel: &str) -> Result<()> {
    let _e = pushenv("RUST_ANALYZER_CHANNEL", release_channel);
    let _e = pushenv("CARGO_PROFILE_RELEASE_LTO", "thin");
    let _e = pushenv("CARGO_PROFILE_RELEASE_DEBUG", "1");

    let target = get_target();
    if target.contains("-linux-gnu") || target.contains("-linux-musl") {
        env::set_var("CC", "clang");
    }

    cmd!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target} --release").run()?;

    let suffix = exe_suffix(&target);
    let src =
        Path::new("target").join(&target).join("release").join(format!("rust-analyzer{}", suffix));
    let dst = Path::new("dist").join(format!("rust-analyzer-{}{}", target, suffix));
    gzip(&src, &dst.with_extension("gz"))?;

    Ok(())
}

fn get_target() -> String {
    match env::var("RA_TARGET") {
        Ok(target) => target,
        _ => {
            if cfg!(target_os = "linux") {
                "x86_64-unknown-linux-gnu".to_string()
            } else if cfg!(target_os = "windows") {
                "x86_64-pc-windows-msvc".to_string()
            } else if cfg!(target_os = "macos") {
                "x86_64-apple-darwin".to_string()
            } else {
                panic!("Unsupported OS, maybe try setting RA_TARGET")
            }
        }
    }
}

fn exe_suffix(target: &str) -> String {
    if target.contains("-windows-") {
        ".exe".into()
    } else {
        "".into()
    }
}

fn gzip(src_path: &Path, dest_path: &Path) -> Result<()> {
    let mut encoder = GzEncoder::new(File::create(dest_path)?, Compression::best());
    let mut input = io::BufReader::new(File::open(src_path)?);
    io::copy(&mut input, &mut encoder)?;
    encoder.finish()?;
    Ok(())
}

struct Patch {
    path: PathBuf,
    original_contents: String,
    contents: String,
}

impl Patch {
    fn new(path: impl Into<PathBuf>) -> Result<Patch> {
        let path = path.into();
        let contents = read_file(&path)?;
        Ok(Patch { path, original_contents: contents.clone(), contents })
    }

    fn replace(&mut self, from: &str, to: &str) -> &mut Patch {
        assert!(self.contents.contains(from));
        self.contents = self.contents.replace(from, to);
        self
    }

    fn commit(&self) -> Result<()> {
        write_file(&self.path, &self.contents)?;
        Ok(())
    }
}

impl Drop for Patch {
    fn drop(&mut self) {
        write_file(&self.path, &self.original_contents).unwrap();
    }
}
<commit_msg>internal: disable debuginfo afterall<commit_after>use std::{
    env,
    fs::File,
    io,
    path::{Path, PathBuf},
};

use anyhow::Result;
use flate2::{write::GzEncoder, Compression};
use xshell::{cmd, mkdir_p, pushd, pushenv, read_file, rm_rf, write_file};

use crate::{date_iso, flags, project_root};

impl flags::Dist {
    pub(crate) fn run(self) -> Result<()> {
        let stable =
            std::env::var("GITHUB_REF").unwrap_or_default().as_str() == "refs/heads/release";

        let dist = project_root().join("dist");
        rm_rf(&dist)?;
        mkdir_p(&dist)?;

        if let Some(patch_version) = self.client_patch_version {
            let version = if stable {
                format!("0.2.{}", patch_version)
            } else {
                // A hack to make VS Code prefer nightly over stable.
                format!("0.3.{}", patch_version)
            };
            let release_tag = if stable { date_iso()? } else { "nightly".to_string() };
            dist_client(&version, &release_tag)?;
        }
        let release_channel = if stable { "stable" } else { "nightly" };
        dist_server(release_channel)?;
        Ok(())
    }
}

fn dist_client(version: &str, release_tag: &str) -> Result<()> {
    let _d = pushd("./editors/code")?;
    let nightly = release_tag == "nightly";

    let mut patch = Patch::new("./package.json")?;

    patch
        .replace(r#""version": "0.4.0-dev""#, &format!(r#""version": "{}""#, version))
        .replace(r#""releaseTag": null"#, &format!(r#""releaseTag": "{}""#, release_tag))
        .replace(r#""$generated-start": false,"#, "")
        .replace(",\n                \"$generated-end\": false", "");

    if nightly {
        patch.replace(
            r#""displayName": "rust-analyzer""#,
            r#""displayName": "rust-analyzer (nightly)""#,
        );
    }
    if !nightly {
        patch.replace(r#""enableProposedApi": true,"#, r#""#);
    }
    patch.commit()?;

    cmd!("npm ci").run()?;
    cmd!("npx vsce package -o ../../dist/rust-analyzer.vsix").run()?;
    Ok(())
}

fn dist_server(release_channel: &str) -> Result<()> {
    let _e = pushenv("RUST_ANALYZER_CHANNEL", release_channel);
    let _e = pushenv("CARGO_PROFILE_RELEASE_LTO", "thin");

    // Uncomment to enable debug info for releases. Note that:
    //   * debug info is split on windows and macs, so it does nothing for those platforms,
    //   * on Linux, this blows up the binary size from 8MB to 43MB, which is unreasonable.
    // let _e = pushenv("CARGO_PROFILE_RELEASE_DEBUG", "1");

    let target = get_target();
    if target.contains("-linux-gnu") || target.contains("-linux-musl") {
        env::set_var("CC", "clang");
    }

    cmd!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target} --release").run()?;

    let suffix = exe_suffix(&target);
    let src =
        Path::new("target").join(&target).join("release").join(format!("rust-analyzer{}", suffix));
    let dst = Path::new("dist").join(format!("rust-analyzer-{}{}", target, suffix));
    gzip(&src, &dst.with_extension("gz"))?;

    Ok(())
}

fn get_target() -> String {
    match env::var("RA_TARGET") {
        Ok(target) => target,
        _ => {
            if cfg!(target_os = "linux") {
                "x86_64-unknown-linux-gnu".to_string()
            } else if cfg!(target_os = "windows") {
                "x86_64-pc-windows-msvc".to_string()
            } else if cfg!(target_os = "macos") {
                "x86_64-apple-darwin".to_string()
            } else {
                panic!("Unsupported OS, maybe try setting RA_TARGET")
            }
        }
    }
}

fn exe_suffix(target: &str) -> String {
    if target.contains("-windows-") {
        ".exe".into()
    } else {
        "".into()
    }
}

fn gzip(src_path: &Path, dest_path: &Path) -> Result<()> {
    let mut encoder = GzEncoder::new(File::create(dest_path)?, Compression::best());
    let mut input = io::BufReader::new(File::open(src_path)?);
    io::copy(&mut input, &mut encoder)?;
    encoder.finish()?;
    Ok(())
}

struct Patch {
    path: PathBuf,
    original_contents: String,
    contents: String,
}

impl Patch {
    fn new(path: impl Into<PathBuf>) -> Result<Patch> {
        let path = path.into();
        let contents = read_file(&path)?;
        Ok(Patch { path, original_contents: contents.clone(), contents })
    }

    fn replace(&mut self, from: &str, to: &str) -> &mut Patch {
        assert!(self.contents.contains(from));
        self.contents = self.contents.replace(from, to);
        self
    }

    fn commit(&self) -> Result<()> {
        write_file(&self.path, &self.contents)?;
        Ok(())
    }
}

impl Drop for Patch {
    fn drop(&mut self) {
        write_file(&self.path, &self.original_contents).unwrap();
    }
}
<|endoftext|>


<commit_before>//! Utility functions for utf8 string slices.
//!
//! This module provides various utility functions that operate on string
//! slices in ways compatible with Ropey.  They may be useful when building
//! additional functionality on top of Ropey.

pub(crate) use str_indices::chars::count as count_chars;
pub use str_indices::chars::from_byte_idx as byte_to_char_idx;
pub use str_indices::chars::to_byte_idx as char_to_byte_idx;
pub(crate) use str_indices::utf16::count_surrogates as count_utf16_surrogates;

// Determine which line implementation to use.
#[cfg(feature = "unicode_lines")]
use str_indices::lines;
#[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
use str_indices::lines_crlf as lines;
#[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
use str_indices::lines_lf as lines;

pub(crate) use self::lines::count_breaks as count_line_breaks;
pub use self::lines::from_byte_idx as byte_to_line_idx;
pub use self::lines::to_byte_idx as line_to_byte_idx;

/// Converts from char-index to line-index in a string slice.
///
/// This is equivalent to counting the line endings before the given char.
///
/// Any past-the-end index will return the last line index.
///
/// Runs in O(N) time.
#[inline]
pub fn char_to_line_idx(text: &str, char_idx: usize) -> usize {
    str_indices::lines::from_byte_idx(text, str_indices::chars::to_byte_idx(text, char_idx))
}

/// Converts from line-index to char-index in a string slice.
///
/// More specifically, this returns the index of the first char of the given line.
///
/// Any past-the-end index will return the one-past-the-end char index.
///
/// Runs in O(N) time.
#[inline]
pub fn line_to_char_idx(text: &str, line_idx: usize) -> usize {
    str_indices::chars::from_byte_idx(text, str_indices::lines::to_byte_idx(text, line_idx))
}

//-------------------------------------------------------------

pub(crate) fn byte_to_utf16_surrogate_idx(text: &str, byte_idx: usize) -> usize {
    let mut i = byte_idx;
    while !text.is_char_boundary(i) {
        i -= 1;
    }
    str_indices::utf16::count_surrogates(&text[..i])
}

pub(crate) fn utf16_code_unit_to_char_idx(text: &str, utf16_idx: usize) -> usize {
    str_indices::chars::from_byte_idx(text, str_indices::utf16::to_byte_idx(text, utf16_idx))
}

/// Returns the byte position just after the second-to-last line break
/// in `text`, or zero of there is no second-to-last line break.
///
/// This function is narrow in scope, only being used for iterating
/// backwards over the lines of a `str`.
pub(crate) fn prev_line_end_char_idx(text: &str) -> usize {
    let mut itr = text.bytes().enumerate().rev();

    // This code always needs to execute, but the variable is only needed
    // for certain feature sets, so silence the warning.
    #[allow(unused_variables)]
    let first_byte = if let Some((_, byte)) = itr.next() {
        byte
    } else {
        return 0;
    };

    while let Some((idx, byte)) = itr.next() {
        match byte {
            0x0A => {
                return idx + 1;
            }
            0x0D =>
            {
                #[cfg(any(feature = "cr_lines", feature = "unicode_lines"))]
                if first_byte != 0x0A {
                    return idx + 1;
                }
            }
            0x0B | 0x0C => {
                #[cfg(feature = "unicode_lines")]
                return idx + 1;
            }
            0x85 =>
            {
                #[cfg(feature = "unicode_lines")]
                if let Some((_, 0xC2)) = itr.next() {
                    return idx + 1;
                }
            }
            0xA8 | 0xA9 =>
            {
                #[cfg(feature = "unicode_lines")]
                if let Some((_, 0x80)) = itr.next() {
                    if let Some((_, 0xE2)) = itr.next() {
                        return idx + 1;
                    }
                }
            }
            _ => {}
        }
    }

    return 0;
}

/// Returns whether the given string ends in a line break or not.
#[inline]
pub(crate) fn ends_with_line_break(text: &str) -> bool {
    if text.is_empty() {
        return false;
    }
    // Find the starting boundary of the last codepoint.
    let mut i = text.len() - 1;
    while !text.is_char_boundary(i) {
        i -= 1;
    }

    // Check if the last codepoint is a line break.

    #[cfg(feature = "unicode_lines")]
    return matches!(
        &text[i..],
        "\u{000A}" | "\u{000B}" | "\u{000C}" | "\u{000D}" | "\u{0085}" | "\u{2028}" | "\u{2029}"
    );

    #[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
    return matches!(&text[i..], "\u{000A}" | "\u{000D}");

    #[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
    return &text[i..] == "\u{000A}";
}

//======================================================================

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

    #[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
    #[test]
    fn prev_line_end_char_idx_lf_01() {
        let mut text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                        There\u{2028}is something.\u{2029}";

        assert_eq!(48, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(8, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(1, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(0, text.len());
    }

    #[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
    #[test]
    fn prev_line_end_char_idx_crlf_01() {
        let mut text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                        There\u{2028}is something.\u{2029}";

        assert_eq!(48, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(9, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(8, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(1, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(0, text.len());
    }

    #[cfg(feature = "unicode_lines")]
    #[test]
    fn prev_line_end_char_idx_unicode_01() {
        let mut text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                        There\u{2028}is something.\u{2029}";

        assert_eq!(48, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(32, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(22, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(17, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(13, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(9, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(8, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(1, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(0, text.len());
    }

    #[test]
    fn ends_with_line_break_01() {
        assert_eq!(true, ends_with_line_break("\n"));

        #[cfg(any(feature = "cr_lines", feature = "unicode_lines"))]
        assert_eq!(true, ends_with_line_break("\r"));

        #[cfg(feature = "unicode_lines")]
        {
            assert_eq!(true, ends_with_line_break("\u{000A}"));
            assert_eq!(true, ends_with_line_break("\u{000B}"));
            assert_eq!(true, ends_with_line_break("\u{000C}"));
            assert_eq!(true, ends_with_line_break("\u{000D}"));
            assert_eq!(true, ends_with_line_break("\u{0085}"));
            assert_eq!(true, ends_with_line_break("\u{2028}"));
            assert_eq!(true, ends_with_line_break("\u{2029}"));
        }
    }

    #[test]
    fn ends_with_line_break_02() {
        assert_eq!(true, ends_with_line_break("Hi there!\n"));

        #[cfg(any(feature = "cr_lines", feature = "unicode_lines"))]
        assert_eq!(true, ends_with_line_break("Hi there!\r"));

        #[cfg(feature = "unicode_lines")]
        {
            assert_eq!(true, ends_with_line_break("Hi there!\u{000A}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{000B}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{000C}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{000D}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{0085}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{2028}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{2029}"));
        }
    }

    #[test]
    fn ends_with_line_break_03() {
        assert_eq!(false, ends_with_line_break(""));
        assert_eq!(false, ends_with_line_break("a"));
        assert_eq!(false, ends_with_line_break("Hi there!"));
    }

    #[test]
    fn ends_with_line_break_04() {
        assert_eq!(false, ends_with_line_break("\na"));
        assert_eq!(false, ends_with_line_break("\ra"));
        assert_eq!(false, ends_with_line_break("\u{000A}a"));
        assert_eq!(false, ends_with_line_break("\u{000B}a"));
        assert_eq!(false, ends_with_line_break("\u{000C}a"));
        assert_eq!(false, ends_with_line_break("\u{000D}a"));
        assert_eq!(false, ends_with_line_break("\u{0085}a"));
        assert_eq!(false, ends_with_line_break("\u{2028}a"));
        assert_eq!(false, ends_with_line_break("\u{2029}a"));
    }
}
<commit_msg>Fix stupid bug in line break feature flag implementation.<commit_after>//! Utility functions for utf8 string slices.
//!
//! This module provides various utility functions that operate on string
//! slices in ways compatible with Ropey.  They may be useful when building
//! additional functionality on top of Ropey.

pub(crate) use str_indices::chars::count as count_chars;
pub use str_indices::chars::from_byte_idx as byte_to_char_idx;
pub use str_indices::chars::to_byte_idx as char_to_byte_idx;
pub(crate) use str_indices::utf16::count_surrogates as count_utf16_surrogates;

// Determine which line implementation to use.
#[cfg(feature = "unicode_lines")]
use str_indices::lines;
#[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
use str_indices::lines_crlf as lines;
#[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
use str_indices::lines_lf as lines;

pub(crate) use self::lines::count_breaks as count_line_breaks;
pub use self::lines::from_byte_idx as byte_to_line_idx;
pub use self::lines::to_byte_idx as line_to_byte_idx;

/// Converts from char-index to line-index in a string slice.
///
/// This is equivalent to counting the line endings before the given char.
///
/// Any past-the-end index will return the last line index.
///
/// Runs in O(N) time.
#[inline]
pub fn char_to_line_idx(text: &str, char_idx: usize) -> usize {
    lines::from_byte_idx(text, str_indices::chars::to_byte_idx(text, char_idx))
}

/// Converts from line-index to char-index in a string slice.
///
/// More specifically, this returns the index of the first char of the given line.
///
/// Any past-the-end index will return the one-past-the-end char index.
///
/// Runs in O(N) time.
#[inline]
pub fn line_to_char_idx(text: &str, line_idx: usize) -> usize {
    str_indices::chars::from_byte_idx(text, lines::to_byte_idx(text, line_idx))
}

//-------------------------------------------------------------

pub(crate) fn byte_to_utf16_surrogate_idx(text: &str, byte_idx: usize) -> usize {
    let mut i = byte_idx;
    while !text.is_char_boundary(i) {
        i -= 1;
    }
    str_indices::utf16::count_surrogates(&text[..i])
}

pub(crate) fn utf16_code_unit_to_char_idx(text: &str, utf16_idx: usize) -> usize {
    str_indices::chars::from_byte_idx(text, str_indices::utf16::to_byte_idx(text, utf16_idx))
}

/// Returns the byte position just after the second-to-last line break
/// in `text`, or zero of there is no second-to-last line break.
///
/// This function is narrow in scope, only being used for iterating
/// backwards over the lines of a `str`.
pub(crate) fn prev_line_end_char_idx(text: &str) -> usize {
    let mut itr = text.bytes().enumerate().rev();

    // This code always needs to execute, but the variable is only needed
    // for certain feature sets, so silence the warning.
    #[allow(unused_variables)]
    let first_byte = if let Some((_, byte)) = itr.next() {
        byte
    } else {
        return 0;
    };

    while let Some((idx, byte)) = itr.next() {
        match byte {
            0x0A => {
                return idx + 1;
            }
            0x0D =>
            {
                #[cfg(any(feature = "cr_lines", feature = "unicode_lines"))]
                if first_byte != 0x0A {
                    return idx + 1;
                }
            }
            0x0B | 0x0C => {
                #[cfg(feature = "unicode_lines")]
                return idx + 1;
            }
            0x85 =>
            {
                #[cfg(feature = "unicode_lines")]
                if let Some((_, 0xC2)) = itr.next() {
                    return idx + 1;
                }
            }
            0xA8 | 0xA9 =>
            {
                #[cfg(feature = "unicode_lines")]
                if let Some((_, 0x80)) = itr.next() {
                    if let Some((_, 0xE2)) = itr.next() {
                        return idx + 1;
                    }
                }
            }
            _ => {}
        }
    }

    return 0;
}

/// Returns whether the given string ends in a line break or not.
#[inline]
pub(crate) fn ends_with_line_break(text: &str) -> bool {
    if text.is_empty() {
        return false;
    }
    // Find the starting boundary of the last codepoint.
    let mut i = text.len() - 1;
    while !text.is_char_boundary(i) {
        i -= 1;
    }

    // Check if the last codepoint is a line break.

    #[cfg(feature = "unicode_lines")]
    return matches!(
        &text[i..],
        "\u{000A}" | "\u{000B}" | "\u{000C}" | "\u{000D}" | "\u{0085}" | "\u{2028}" | "\u{2029}"
    );

    #[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
    return matches!(&text[i..], "\u{000A}" | "\u{000D}");

    #[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
    return &text[i..] == "\u{000A}";
}

//======================================================================

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

    #[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
    #[test]
    fn prev_line_end_char_idx_lf_01() {
        let mut text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                        There\u{2028}is something.\u{2029}";

        assert_eq!(48, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(8, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(1, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(0, text.len());
    }

    #[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
    #[test]
    fn prev_line_end_char_idx_crlf_01() {
        let mut text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                        There\u{2028}is something.\u{2029}";

        assert_eq!(48, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(9, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(8, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(1, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(0, text.len());
    }

    #[cfg(feature = "unicode_lines")]
    #[test]
    fn prev_line_end_char_idx_unicode_01() {
        let mut text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                        There\u{2028}is something.\u{2029}";

        assert_eq!(48, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(32, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(22, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(17, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(13, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(9, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(8, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(1, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(0, text.len());
    }

    #[test]
    fn ends_with_line_break_01() {
        assert_eq!(true, ends_with_line_break("\n"));

        #[cfg(any(feature = "cr_lines", feature = "unicode_lines"))]
        assert_eq!(true, ends_with_line_break("\r"));

        #[cfg(feature = "unicode_lines")]
        {
            assert_eq!(true, ends_with_line_break("\u{000A}"));
            assert_eq!(true, ends_with_line_break("\u{000B}"));
            assert_eq!(true, ends_with_line_break("\u{000C}"));
            assert_eq!(true, ends_with_line_break("\u{000D}"));
            assert_eq!(true, ends_with_line_break("\u{0085}"));
            assert_eq!(true, ends_with_line_break("\u{2028}"));
            assert_eq!(true, ends_with_line_break("\u{2029}"));
        }
    }

    #[test]
    fn ends_with_line_break_02() {
        assert_eq!(true, ends_with_line_break("Hi there!\n"));

        #[cfg(any(feature = "cr_lines", feature = "unicode_lines"))]
        assert_eq!(true, ends_with_line_break("Hi there!\r"));

        #[cfg(feature = "unicode_lines")]
        {
            assert_eq!(true, ends_with_line_break("Hi there!\u{000A}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{000B}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{000C}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{000D}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{0085}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{2028}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{2029}"));
        }
    }

    #[test]
    fn ends_with_line_break_03() {
        assert_eq!(false, ends_with_line_break(""));
        assert_eq!(false, ends_with_line_break("a"));
        assert_eq!(false, ends_with_line_break("Hi there!"));
    }

    #[test]
    fn ends_with_line_break_04() {
        assert_eq!(false, ends_with_line_break("\na"));
        assert_eq!(false, ends_with_line_break("\ra"));
        assert_eq!(false, ends_with_line_break("\u{000A}a"));
        assert_eq!(false, ends_with_line_break("\u{000B}a"));
        assert_eq!(false, ends_with_line_break("\u{000C}a"));
        assert_eq!(false, ends_with_line_break("\u{000D}a"));
        assert_eq!(false, ends_with_line_break("\u{0085}a"));
        assert_eq!(false, ends_with_line_break("\u{2028}a"));
        assert_eq!(false, ends_with_line_break("\u{2029}a"));
    }

    #[test]
    fn char_to_line_idx_01() {
        let text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                    There\u{2028}is something.\u{2029}";

        #[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
        {
            assert_eq!(0, char_to_line_idx(text, 0));
            assert_eq!(1, char_to_line_idx(text, 1));
            assert_eq!(2, char_to_line_idx(text, 8));
            assert_eq!(2, char_to_line_idx(text, 38));
        }

        #[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
        {
            assert_eq!(0, char_to_line_idx(text, 0));
            assert_eq!(1, char_to_line_idx(text, 1));
            assert_eq!(2, char_to_line_idx(text, 8));
            assert_eq!(3, char_to_line_idx(text, 9));
            assert_eq!(3, char_to_line_idx(text, 38));
        }

        #[cfg(feature = "unicode_lines")]
        {
            assert_eq!(0, char_to_line_idx(text, 0));
            assert_eq!(1, char_to_line_idx(text, 1));
            assert_eq!(2, char_to_line_idx(text, 8));
            assert_eq!(3, char_to_line_idx(text, 9));
            assert_eq!(4, char_to_line_idx(text, 11));
            assert_eq!(5, char_to_line_idx(text, 13));
            assert_eq!(6, char_to_line_idx(text, 15));
            assert_eq!(7, char_to_line_idx(text, 23));
            assert_eq!(8, char_to_line_idx(text, 37));
            assert_eq!(8, char_to_line_idx(text, 38));
        }
    }

    #[test]
    fn line_to_char_idx_01() {
        let text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                    There\u{2028}is something.\u{2029}";

        #[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
        {
            assert_eq!(0, line_to_char_idx(text, 0));
            assert_eq!(1, line_to_char_idx(text, 1));
            assert_eq!(8, line_to_char_idx(text, 2));
            assert_eq!(37, line_to_char_idx(text, 3));
        }

        #[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
        {
            assert_eq!(0, line_to_char_idx(text, 0));
            assert_eq!(1, line_to_char_idx(text, 1));
            assert_eq!(8, line_to_char_idx(text, 2));
            assert_eq!(9, line_to_char_idx(text, 3));
            assert_eq!(37, line_to_char_idx(text, 4));
        }

        #[cfg(feature = "unicode_lines")]
        {
            assert_eq!(0, line_to_char_idx(text, 0));
            assert_eq!(1, line_to_char_idx(text, 1));
            assert_eq!(8, line_to_char_idx(text, 2));
            assert_eq!(9, line_to_char_idx(text, 3));
            assert_eq!(11, line_to_char_idx(text, 4));
            assert_eq!(13, line_to_char_idx(text, 5));
            assert_eq!(15, line_to_char_idx(text, 6));
            assert_eq!(23, line_to_char_idx(text, 7));
            assert_eq!(37, line_to_char_idx(text, 8));
            assert_eq!(37, line_to_char_idx(text, 9));
        }
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;

fn main() {
    println!("Hello, world!");

    let x = Rc::new(5i);
    let y = x.clone();

    println!("{} {}", *x, *y);
}
<commit_msg>int type<commit_after>use std::rc::Rc;

fn main() {
    println!("Hello, world!");

    let x = Rc::new(5i32);
    let y = x.clone();

    println!("{} {}", *x, *y);
}
<|endoftext|>


<commit_before>macro_rules! add_impl {
    ($t:ty, $m:ident) => (
        mod $m {
            #[allow(unused_imports)]
            use tensor::Tensor;
            type T = Tensor<$t>;

            #[test]
            fn matrix_matrix_1() {
                // Test square matrices
                let t1 = T::new(vec![ 0.0, 3.0, 2.0, 10.0]).reshape(&[2, 2]);
                let t2 = T::new(vec![-2.0, 1.0, 8.0,  0.0]).reshape(&[2, 2]);
                let answer = T::new(vec![24.0, 0.0, 76.0, 2.0]).reshape(&[2, 2]);
                assert!(t1.dot(&t2) == answer);
            }

            #[test]
            fn matrix_matrix_2() {
                let t1 = T::new(vec![ 0.0, 3.0, 2.0, 10.0, -3.0, 0.0]).reshape(&[3, 2]);
                let t2 = T::new(vec![-2.0, 1.0, 8.0,  0.0]).reshape(&[2, 2]);
                let answer = T::new(vec![24.0, 0.0, 76.0, 2.0, 6.0, -3.0]).reshape(&[3, 2]);
                assert!(t1.dot(&t2) == answer);
            }

            #[test]
            fn matrix_vector_1() {
                let t1 = T::new(vec![ 0.0, 3.0, 2.0, 10.0, -3.0, 0.0]).reshape(&[3, 2]);
                //let t1 = T::new(vec![ 0.0, 2.0, -3.0, 3.0, 10.0, 0.0]).reshape(&[3, 2]);
                let t2 = T::new(vec![-2.0, 1.0]);
                let answer = T::new(vec![3.0, 6.0, 6.0]);
                assert!(t1.dot(&t2) == answer);
            }

            #[test]
            fn vector_vector_1() {
                let t1 = T::new(vec![ 0.0, 3.0, 2.0, 10.0, -3.0, 0.0]);
                let t2 = T::new(vec![-2.0, 1.0, 3.0, -2.0, -3.0, 1.0]);
                let answer = T::new(vec![-2.0]);
                assert!(t1.dot(&t2) == answer);
            }
        }
    )
}

add_impl!(f32, float32);
add_impl!(f64, float64);
<commit_msg>Fixed dot test to use proper scalars too<commit_after>macro_rules! add_impl {
    ($t:ty, $m:ident) => (
        mod $m {
            #[allow(unused_imports)]
            use tensor::Tensor;
            type T = Tensor<$t>;

            #[test]
            fn matrix_matrix_1() {
                // Test square matrices
                let t1 = T::new(vec![ 0.0, 3.0, 2.0, 10.0]).reshape(&[2, 2]);
                let t2 = T::new(vec![-2.0, 1.0, 8.0,  0.0]).reshape(&[2, 2]);
                let answer = T::new(vec![24.0, 0.0, 76.0, 2.0]).reshape(&[2, 2]);
                assert!(t1.dot(&t2) == answer);
            }

            #[test]
            fn matrix_matrix_2() {
                let t1 = T::new(vec![ 0.0, 3.0, 2.0, 10.0, -3.0, 0.0]).reshape(&[3, 2]);
                let t2 = T::new(vec![-2.0, 1.0, 8.0,  0.0]).reshape(&[2, 2]);
                let answer = T::new(vec![24.0, 0.0, 76.0, 2.0, 6.0, -3.0]).reshape(&[3, 2]);
                assert!(t1.dot(&t2) == answer);
            }

            #[test]
            fn matrix_vector_1() {
                let t1 = T::new(vec![ 0.0, 3.0, 2.0, 10.0, -3.0, 0.0]).reshape(&[3, 2]);
                //let t1 = T::new(vec![ 0.0, 2.0, -3.0, 3.0, 10.0, 0.0]).reshape(&[3, 2]);
                let t2 = T::new(vec![-2.0, 1.0]);
                let answer = T::new(vec![3.0, 6.0, 6.0]);
                assert!(t1.dot(&t2) == answer);
            }

            #[test]
            fn vector_vector_1() {
                let t1 = T::new(vec![ 0.0, 3.0, 2.0, 10.0, -3.0, 0.0]);
                let t2 = T::new(vec![-2.0, 1.0, 3.0, -2.0, -3.0, 1.0]);
                let answer = T::fscalar(-2.0);
                assert!(t1.dot(&t2) == answer);
            }
        }
    )
}

add_impl!(f32, float32);
add_impl!(f64, float64);
<|endoftext|>