<commit_before>//***********************************************************************
//  Copyright 2006 John A. Trangenstein
//
//  This software is made available for research and instructional use
//  only.e available for research and instructional use
//  only.
//  You may copy and use this software without charge for these
//  non-commercial purposes, provided that the copyright notice and
//  associated text is reproduced on all copies.
//  For all other uses (including distribution of modified versions),
//  please contact the author at
//    John A. Trangenstein
//    Department of Mathematics
//    Duke University
//    Durham, NC 27708-0320
//    USA
//  or
//    johnt@math.duke.edu
//
//  This software is made available "as is" without any assurance that it
//  is completely correct, or that it will work for your purposes.
//  Use the software at your own risk.
//***********************************************************************

// Permission to publish the translation of the code
// was graciously granted by Prof. John A. Trangenstein

// The MIT License (MIT)
//
// Copyright (c) 2015 Alexander Samoilov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#![feature(duration_span)]

extern crate argparse;
extern crate num;

use num::{Num, Zero, One, Signed};
use std::iter::FromIterator;
use std::cmp::Ordering;

use std::time::Duration;
use std::cmp;
use std::process::exit;
use argparse::{ArgumentParser, StoreTrue, Store};

struct Options {
    verbose: bool,
    num_steps: usize,
    num_cells: usize,
    num_runs: usize,
}

fn min_dx(x: &[f64]) -> f64 {
    // https://doc.rust-lang.org/std/primitive.slice.html#method.windows
    let mdx = x.windows(2) // iterator for adjacent pairs of a slice
               .map(|w| w[1]-w[0]) // i.e. [x[0], x[1]], [x[1], x[2]] ...
               .fold(std::f64::MAX, |x1, x2| x1.min(x2)); // `fold` to find `min`
    mdx
}

#[test]
fn test_min_dx() {

    fn sub<T: Num + Copy>(lhs: &[T], rhs: &[T]) -> Vec<T> {
        Vec::from_iter (lhs.iter().zip(rhs.iter()) .map(|(&x,&y)| x - y ) )
    }

    // 1. prepare non-equidistant vector `x`
    let base_dx = std::f64::consts::FRAC_PI_4; // 0.785398
    let mut x = Vec::from_iter ((1..7) .map(|idx| ((idx as f64).sin() * base_dx).cos().abs() ) );

    x.sort_by(|&x, &y|
        if      x < y { Ordering::Less }
        else if x > y { Ordering::Greater }
        else { Ordering::Equal } );

    let delta_x = sub(&x, &[0.7295467223444416, 0.7556433468867207, 0.7894463883160331,
                            0.8284895327495356, 0.9760168013869176, 0.9938640428738624]);

    let inf_norm = delta_x .iter() .fold(delta_x[0].abs(), |x1, x2| (x1).max((*x2).abs()));

    assert!(inf_norm < 1e-10, "inf_norm");

    // classical way
    let mut min_dx1 = std::f64::MAX;
    for i in 0 .. x.len()-1 {
        min_dx1 = min_dx1.min(x[i+1]-x[i]);
    }

    // functional way
    let min_dx2 = min_dx(&x);
    let abs_delta = (min_dx1 - min_dx2).abs();
    println!("abs_delta : {} min_dx1 : {} min_dx2 : {} x : {:?}", abs_delta, min_dx1, min_dx2, x);
    assert!(abs_delta < 1e-10, "min_dx");
}

fn do_computation(nsteps: usize, ncells: usize, tmax: f64, ifirst: usize, ilast: usize,
                  statelft: f64, statergt: f64, velocity: f64, dt: f64,
                  fc: usize, lc: usize, x: &Vec<f64>, u: &mut Vec<f64>,
                  fp_way: bool)
{
    let mut istep   =   0;
    let mut t       =   0.0f64;
    let mut flux    =   vec![0.0f64; x.len()];

    // loop over timesteps
    while istep < nsteps && t < tmax {

        // right boundary condition: outgoing wave
        for ic in ncells .. lc {
            u[ic+2]=u[ncells+1];
        }
        // left boundary condition: specified value
        for ic in 0 .. fc {
            u[ic+2]=statelft;
        }

        // upwind fluxes times dt (ie, flux time integral over cell side)
        // assumes velocity > 0
        let vdt=velocity*dt;
        for ie in ifirst .. ilast+1 {
            flux[ie]=vdt*u[ie+1];
        }

        // conservative difference
        if !fp_way {
            for ic in ifirst .. ilast {
                u[ic+2] -= (flux[ic+1]-flux[ic]) / (x[ic+1]-x[ic])
            }
        } else {
            let dfdx = Vec::from_iter( flux.windows(2)
                                    .zip( x.windows(2) )
                                           .map(|(f,x)|
                                            (f[1] - f[0]) / (x[1] - x[0]) ) );
            for ic in ifirst .. ilast {
                u[ic+2] -= dfdx[ic];
            }
        }

        // update time and step number
        t       +=  dt;
        istep   +=  1
    }
}

fn main() {
    let mut options = Options {
        verbose:   false,
        num_steps: 2000,
        num_cells: 2000,
        num_runs:  10,
    };

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Time elapsing of model PDE for scalar conservation law.");
        ap.refer(&mut options.verbose)
            .add_option(&["-v", "--verbose"], StoreTrue,
            "set verbose");
        ap.refer(&mut options.num_steps)
            .add_option(&["-t", "--num_steps"], Store,
            "set number of time steps");
        ap.refer(&mut options.num_cells)
            .add_option(&["-n", "--num_cells"], Store,
            "set number of grid cells");
        ap.refer(&mut options.num_runs)
            .add_option(&["-b", "--num_runs"], Store,
            "set number of runs");
        match ap.parse_args() {
            Ok(()) => {}
            Err(x) => {
                exit(x);
            }
        }
    }

    if options.verbose {
        println!("number of time steps : {} number of grid cells : {} number of runs : {}",
                 options.num_steps, options.num_cells, options.num_runs);
    }

    // problem-specific parameters:
    const jump     : f64   =  0.0f64;
    const x_left   : f64   = -0.2f64;
    const x_right  : f64   =  1.0f64;
    const statelft : f64   =  2.0f64;
    const statergt : f64   =  0.0f64;
    const velocity : f64   =  1.0f64;

    const tmax     : f64   =  0.8f64;
    const cfl      : f64   =  0.9f64;

    // array bounds:
    let   nsteps           = options.num_steps;
    let   ncells           = options.num_cells;
    const fc       : usize = 2;
    let   lc               = ncells+2;
    const ifirst   : usize = 1;
    let   ilast            = ncells-1;

    // work arrays
    // #   double precision
    // #  &  u(-2:ncells+1),
    // #  &  x(0:ncells),
    // #  &  flux(0:ncells)

    let mut u    = vec![0.0f64; ncells+4];
    let mut x    = vec![0.0f64; ncells+1];

    //  uniform mesh:
    let dx = (x_right-x_left) / ncells as f64;
    for ie in ifirst .. ilast+1 {
        x[ie] = x_left + ie as f64 * dx;
    }

    // initial values for diffential equation:
    let ijump = cmp::max(ifirst as isize -1,
                         cmp::min((ncells as f64 * (jump-x_left)/(x_right-x_left) + 0.5) as isize,
                                  (ilast+1) as isize)) as usize;
    if options.verbose {
        println!("ijump : {}", ijump);
    }

    // stable timestep (independent of time for linear advection):
    let mindx = min_dx(&x);
    let dt = cfl*mindx/velocity.abs();

    let d = Duration::span(||{
        for r in 0..options.num_runs {
            if options.verbose {
                println!("run number : {}", r);
            }

            // left state to left of jump
            for ic in ifirst .. ijump-1 {
                u[ic+3] = statelft;
            }

            // volume-weighted average in cell containing jump
            let frac = (jump-x_left-ijump as f64 *dx)/(x_right-x_left);
            u[ijump+3] = statelft*frac+statergt*(1.0f64-frac);

            // right state to right of jump
            for ic in ijump+1 .. ilast {
                u[ic+3]=statergt;
            }

            do_computation(nsteps, ncells, tmax, ifirst, ilast,
                           statelft, statergt, velocity, dt, fc, lc, &x, &mut u, true);
        }
    });
    println!("elapsed time: {}s.", d.as_secs() as f64 + d.subsec_nanos() as f64 / 1.0e9f64);
}
<commit_msg>one more index fix.<commit_after>//***********************************************************************
//  Copyright 2006 John A. Trangenstein
//
//  This software is made available for research and instructional use
//  only.e available for research and instructional use
//  only.
//  You may copy and use this software without charge for these
//  non-commercial purposes, provided that the copyright notice and
//  associated text is reproduced on all copies.
//  For all other uses (including distribution of modified versions),
//  please contact the author at
//    John A. Trangenstein
//    Department of Mathematics
//    Duke University
//    Durham, NC 27708-0320
//    USA
//  or
//    johnt@math.duke.edu
//
//  This software is made available "as is" without any assurance that it
//  is completely correct, or that it will work for your purposes.
//  Use the software at your own risk.
//***********************************************************************

// Permission to publish the translation of the code
// was graciously granted by Prof. John A. Trangenstein

// The MIT License (MIT)
//
// Copyright (c) 2015 Alexander Samoilov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#![feature(duration_span)]

extern crate argparse;
extern crate num;

use num::{Num, Zero, One, Signed};
use std::iter::FromIterator;
use std::cmp::Ordering;

use std::time::Duration;
use std::cmp;
use std::process::exit;
use argparse::{ArgumentParser, StoreTrue, Store};

struct Options {
    verbose: bool,
    num_steps: usize,
    num_cells: usize,
    num_runs: usize,
}

fn min_dx(x: &[f64]) -> f64 {
    // https://doc.rust-lang.org/std/primitive.slice.html#method.windows
    let mdx = x.windows(2) // iterator for adjacent pairs of a slice
               .map(|w| w[1]-w[0]) // i.e. [x[0], x[1]], [x[1], x[2]] ...
               .fold(std::f64::MAX, |x1, x2| x1.min(x2)); // `fold` to find `min`
    mdx
}

#[test]
fn test_min_dx() {

    fn sub<T: Num + Copy>(lhs: &[T], rhs: &[T]) -> Vec<T> {
        Vec::from_iter (lhs.iter().zip(rhs.iter()) .map(|(&x,&y)| x - y ) )
    }

    // 1. prepare non-equidistant vector `x`
    let base_dx = std::f64::consts::FRAC_PI_4; // 0.785398
    let mut x = Vec::from_iter ((1..7) .map(|idx| ((idx as f64).sin() * base_dx).cos().abs() ) );

    x.sort_by(|&x, &y|
        if      x < y { Ordering::Less }
        else if x > y { Ordering::Greater }
        else { Ordering::Equal } );

    let delta_x = sub(&x, &[0.7295467223444416, 0.7556433468867207, 0.7894463883160331,
                            0.8284895327495356, 0.9760168013869176, 0.9938640428738624]);

    let inf_norm = delta_x .iter() .fold(delta_x[0].abs(), |x1, x2| (x1).max((*x2).abs()));

    assert!(inf_norm < 1e-10, "inf_norm");

    // classical way
    let mut min_dx1 = std::f64::MAX;
    for i in 0 .. x.len()-1 {
        min_dx1 = min_dx1.min(x[i+1]-x[i]);
    }

    // functional way
    let min_dx2 = min_dx(&x);
    let abs_delta = (min_dx1 - min_dx2).abs();
    println!("abs_delta : {} min_dx1 : {} min_dx2 : {} x : {:?}", abs_delta, min_dx1, min_dx2, x);
    assert!(abs_delta < 1e-10, "min_dx");
}

fn do_computation(nsteps: usize, ncells: usize, tmax: f64, ifirst: usize, ilast: usize,
                  statelft: f64, statergt: f64, velocity: f64, dt: f64,
                  fc: usize, lc: usize, x: &Vec<f64>, u: &mut Vec<f64>,
                  fp_way: bool)
{
    let mut istep   =   0;
    let mut t       =   0.0f64;
    let mut flux    =   vec![0.0f64; x.len()];

    // loop over timesteps
    while istep < nsteps && t < tmax {

        // right boundary condition: outgoing wave
        for ic in ncells .. lc {
            u[ic+2]=u[ncells+1];
        }
        // left boundary condition: specified value
        for ic in 0 .. fc {
            u[ic]=statelft;
        }

        // upwind fluxes times dt (ie, flux time integral over cell side)
        // assumes velocity > 0
        let vdt=velocity*dt;
        for ie in ifirst .. ilast+1 {
            flux[ie]=vdt*u[ie+1];
        }

        // conservative difference
        if !fp_way {
            for ic in ifirst .. ilast {
                u[ic+2] -= (flux[ic+1]-flux[ic]) / (x[ic+1]-x[ic])
            }
        } else {
            let dfdx = Vec::from_iter( flux.windows(2)
                                    .zip( x.windows(2) )
                                           .map(|(f,x)|
                                            (f[1] - f[0]) / (x[1] - x[0]) ) );
            for ic in ifirst .. ilast {
                u[ic+2] -= dfdx[ic];
            }
        }

        // update time and step number
        t       +=  dt;
        istep   +=  1
    }
}

fn main() {
    let mut options = Options {
        verbose:   false,
        num_steps: 2000,
        num_cells: 2000,
        num_runs:  10,
    };

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Time elapsing of model PDE for scalar conservation law.");
        ap.refer(&mut options.verbose)
            .add_option(&["-v", "--verbose"], StoreTrue,
            "set verbose");
        ap.refer(&mut options.num_steps)
            .add_option(&["-t", "--num_steps"], Store,
            "set number of time steps");
        ap.refer(&mut options.num_cells)
            .add_option(&["-n", "--num_cells"], Store,
            "set number of grid cells");
        ap.refer(&mut options.num_runs)
            .add_option(&["-b", "--num_runs"], Store,
            "set number of runs");
        match ap.parse_args() {
            Ok(()) => {}
            Err(x) => {
                exit(x);
            }
        }
    }

    if options.verbose {
        println!("number of time steps : {} number of grid cells : {} number of runs : {}",
                 options.num_steps, options.num_cells, options.num_runs);
    }

    // problem-specific parameters:
    const jump     : f64   =  0.0f64;
    const x_left   : f64   = -0.2f64;
    const x_right  : f64   =  1.0f64;
    const statelft : f64   =  2.0f64;
    const statergt : f64   =  0.0f64;
    const velocity : f64   =  1.0f64;

    const tmax     : f64   =  0.8f64;
    const cfl      : f64   =  0.9f64;

    // array bounds:
    let   nsteps           = options.num_steps;
    let   ncells           = options.num_cells;
    const fc       : usize = 2;
    let   lc               = ncells+2;
    const ifirst   : usize = 1;
    let   ilast            = ncells-1;

    // work arrays
    // #   double precision
    // #  &  u(-2:ncells+1),
    // #  &  x(0:ncells),
    // #  &  flux(0:ncells)

    let mut u    = vec![0.0f64; ncells+4];
    let mut x    = vec![0.0f64; ncells+1];

    //  uniform mesh:
    let dx = (x_right-x_left) / ncells as f64;
    for ie in ifirst .. ilast+1 {
        x[ie] = x_left + ie as f64 * dx;
    }

    // initial values for diffential equation:
    let ijump = cmp::max(ifirst as isize -1,
                         cmp::min((ncells as f64 * (jump-x_left)/(x_right-x_left) + 0.5) as isize,
                                  (ilast+1) as isize)) as usize;
    if options.verbose {
        println!("ijump : {}", ijump);
    }

    // stable timestep (independent of time for linear advection):
    let mindx = min_dx(&x);
    let dt = cfl*mindx/velocity.abs();

    let d = Duration::span(||{
        for r in 0..options.num_runs {
            if options.verbose {
                println!("run number : {}", r);
            }

            // left state to left of jump
            for ic in ifirst .. ijump-1 {
                u[ic+3] = statelft;
            }

            // volume-weighted average in cell containing jump
            let frac = (jump-x_left-ijump as f64 *dx)/(x_right-x_left);
            u[ijump+3] = statelft*frac+statergt*(1.0f64-frac);

            // right state to right of jump
            for ic in ijump+1 .. ilast {
                u[ic+3]=statergt;
            }

            do_computation(nsteps, ncells, tmax, ifirst, ilast,
                           statelft, statergt, velocity, dt, fc, lc, &x, &mut u, true);
        }
    });
    println!("elapsed time: {}s.", d.as_secs() as f64 + d.subsec_nanos() as f64 / 1.0e9f64);
}
<|endoftext|>


<commit_before>#![cfg(test)]

use postgres::Client;
use postgres_types::{FromSqlOwned, ToSql};
use std::fmt;

mod composites;
mod domains;
mod enums;
mod transparent;

pub fn test_type<T, S>(conn: &mut Client, sql_type: &str, checks: &[(T, S)])
where
    T: PartialEq + FromSqlOwned + ToSql + Sync,
    S: fmt::Display,
{
    for &(ref val, ref repr) in checks.iter() {
        let stmt = conn
            .prepare(&*format!("SELECT {}::{}", *repr, sql_type))
            .unwrap();
        let result = conn.query_one(&stmt, &[]).unwrap().get(0);
        assert_eq!(val, &result);

        let stmt = conn.prepare(&*format!("SELECT $1::{}", sql_type)).unwrap();
        let result = conn.query_one(&stmt, &[val]).unwrap().get(0);
        assert_eq!(val, &result);
    }
}

pub fn test_type_asymmetric<T, F, S, C>(
    conn: &mut Client,
    sql_type: &str,
    checks: &[(T, S)],
    cmp: C,
) where
    T: ToSql + Sync,
    F: FromSqlOwned,
    S: fmt::Display,
    C: Fn(&T, &F) -> bool,
{
    for &(ref val, ref repr) in checks.iter() {
        let stmt = conn
            .prepare(&*format!("SELECT {}::{}", *repr, sql_type))
            .unwrap();
        let result: F = conn.query_one(&stmt, &[]).unwrap().get(0);
        assert!(cmp(val, &result));

        let stmt = conn.prepare(&*format!("SELECT $1::{}", sql_type)).unwrap();
        let result: F = conn.query_one(&stmt, &[val]).unwrap().get(0);
        assert!(cmp(val, &result));
    }
}

#[test]
fn compile_fail() {
    trybuild::TestCases::new().compile_fail("src/compile-fail/*.rs");
}
<commit_msg>more clippy<commit_after>#![cfg(test)]

use postgres::Client;
use postgres_types::{FromSqlOwned, ToSql};
use std::fmt;

mod composites;
mod domains;
mod enums;
mod transparent;

pub fn test_type<T, S>(conn: &mut Client, sql_type: &str, checks: &[(T, S)])
where
    T: PartialEq + FromSqlOwned + ToSql + Sync,
    S: fmt::Display,
{
    for &(ref val, ref repr) in checks.iter() {
        let stmt = conn
            .prepare(&format!("SELECT {}::{}", *repr, sql_type))
            .unwrap();
        let result = conn.query_one(&stmt, &[]).unwrap().get(0);
        assert_eq!(val, &result);

        let stmt = conn.prepare(&format!("SELECT $1::{}", sql_type)).unwrap();
        let result = conn.query_one(&stmt, &[val]).unwrap().get(0);
        assert_eq!(val, &result);
    }
}

pub fn test_type_asymmetric<T, F, S, C>(
    conn: &mut Client,
    sql_type: &str,
    checks: &[(T, S)],
    cmp: C,
) where
    T: ToSql + Sync,
    F: FromSqlOwned,
    S: fmt::Display,
    C: Fn(&T, &F) -> bool,
{
    for &(ref val, ref repr) in checks.iter() {
        let stmt = conn
            .prepare(&format!("SELECT {}::{}", *repr, sql_type))
            .unwrap();
        let result: F = conn.query_one(&stmt, &[]).unwrap().get(0);
        assert!(cmp(val, &result));

        let stmt = conn.prepare(&format!("SELECT $1::{}", sql_type)).unwrap();
        let result: F = conn.query_one(&stmt, &[val]).unwrap().get(0);
        assert!(cmp(val, &result));
    }
}

#[test]
fn compile_fail() {
    trybuild::TestCases::new().compile_fail("src/compile-fail/*.rs");
}
<|endoftext|>


<commit_before>use clap::crate_version;

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

use clap::{App, AppSettings, ArgMatches, SubCommand};

use mdbook::errors::Result as Result3;
use mdbook::MDBook;

use failure::Error;
#[cfg(feature = "linkcheck")]
use mdbook::renderer::RenderContext;
#[cfg(feature = "linkcheck")]
use mdbook_linkcheck::{self, errors::BrokenLinks};

fn main() {
    let d_message = "-d, --dest-dir=[dest-dir]
'The output directory for your book{n}(Defaults to ./book when omitted)'";
    let dir_message = "[dir]
'A directory for your book{n}(Defaults to Current Directory when omitted)'";

    let matches = App::new("rustbook")
        .about("Build a book with mdBook")
        .author("Steve Klabnik <steve@steveklabnik.com>")
        .version(&*format!("v{}", crate_version!()))
        .setting(AppSettings::SubcommandRequired)
        .subcommand(
            SubCommand::with_name("build")
                .about("Build the book from the markdown files")
                .arg_from_usage(d_message)
                .arg_from_usage(dir_message),
        )
        .subcommand(
            SubCommand::with_name("linkcheck")
                .about("Run linkcheck with mdBook 3")
                .arg_from_usage(dir_message),
        )
        .get_matches();

    // Check which subcomamnd the user ran...
    match matches.subcommand() {
        ("build", Some(sub_matches)) => {
            if let Err(e) = build(sub_matches) {
                eprintln!("Error: {}", e);

                for cause in e.iter().skip(1) {
                    eprintln!("\tCaused By: {}", cause);
                }

                ::std::process::exit(101);
            }
        }
        ("linkcheck", Some(sub_matches)) => {
            if let Err(err) = linkcheck(sub_matches) {
                eprintln!("Error: {}", err);

                // HACK: ignore timeouts
                #[allow(unused_mut)]
                let mut actually_broken = false;

                #[cfg(feature = "linkcheck")]
                {
                    if let Ok(broken_links) = err.downcast::<BrokenLinks>() {
                        for cause in broken_links.links().iter() {
                            eprintln!("\tCaused By: {}", cause);

                            if cause.contains("timed out") {
                                actually_broken = true;
                            }
                        }
                    }
                }

                if actually_broken {
                    std::process::exit(101);
                } else {
                    std::process::exit(0);
                }
            }
        }
        (_, _) => unreachable!(),
    };
}

#[cfg(feature = "linkcheck")]
pub fn linkcheck(args: &ArgMatches<'_>) -> Result<(), Error> {
    let book_dir = get_book_dir(args);
    let book = MDBook::load(&book_dir).unwrap();
    let cfg = book.config;
    let render_ctx = RenderContext::new(&book_dir, book.book, cfg, &book_dir);

    mdbook_linkcheck::check_links(&render_ctx)
}

#[cfg(not(feature = "linkcheck"))]
pub fn linkcheck(_args: &ArgMatches<'_>) -> Result<(), Error> {
    println!("mdbook-linkcheck is disabled.");
    Ok(())
}

// Build command implementation
pub fn build(args: &ArgMatches<'_>) -> Result3<()> {
    let book_dir = get_book_dir(args);
    let mut book = MDBook::load(&book_dir)?;

    // Set this to allow us to catch bugs in advance.
    book.config.build.create_missing = false;

    if let Some(dest_dir) = args.value_of("dest-dir") {
        book.config.build.build_dir = PathBuf::from(dest_dir);
    }

    book.build()?;

    Ok(())
}

fn get_book_dir(args: &ArgMatches<'_>) -> PathBuf {
    if let Some(dir) = args.value_of("dir") {
        // Check if path is relative from current dir, or absolute...
        let p = Path::new(dir);
        if p.is_relative() {
            env::current_dir().unwrap().join(dir)
        } else {
            p.to_path_buf()
        }
    } else {
        env::current_dir().unwrap()
    }
}
<commit_msg>fix bugs + review comments<commit_after>use clap::crate_version;

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

use clap::{App, AppSettings, ArgMatches, SubCommand};

use mdbook::errors::Result as Result3;
use mdbook::MDBook;

use failure::Error;
#[cfg(feature = "linkcheck")]
use mdbook::renderer::RenderContext;
#[cfg(feature = "linkcheck")]
use mdbook_linkcheck::{self, errors::BrokenLinks};

fn main() {
    let d_message = "-d, --dest-dir=[dest-dir]
'The output directory for your book{n}(Defaults to ./book when omitted)'";
    let dir_message = "[dir]
'A directory for your book{n}(Defaults to Current Directory when omitted)'";

    let matches = App::new("rustbook")
        .about("Build a book with mdBook")
        .author("Steve Klabnik <steve@steveklabnik.com>")
        .version(&*format!("v{}", crate_version!()))
        .setting(AppSettings::SubcommandRequired)
        .subcommand(
            SubCommand::with_name("build")
                .about("Build the book from the markdown files")
                .arg_from_usage(d_message)
                .arg_from_usage(dir_message),
        )
        .subcommand(
            SubCommand::with_name("linkcheck")
                .about("Run linkcheck with mdBook 3")
                .arg_from_usage(dir_message),
        )
        .get_matches();

    // Check which subcomamnd the user ran...
    match matches.subcommand() {
        ("build", Some(sub_matches)) => {
            if let Err(e) = build(sub_matches) {
                eprintln!("Error: {}", e);

                for cause in e.iter().skip(1) {
                    eprintln!("\tCaused By: {}", cause);
                }

                ::std::process::exit(101);
            }
        }
        ("linkcheck", Some(sub_matches)) => {
            if let Err(err) = linkcheck(sub_matches) {
                eprintln!("Error: {}", err);

                // HACK: ignore timeouts
                let actually_broken = {
                    #[cfg(feature = "linkcheck")]
                    {
                        err.downcast::<BrokenLinks>()
                            .unwrap_or(false)
                            .links()
                            .iter()
                            .inspect(|cause| eprintln!("\tCaused By: {}", cause))
                            .any(|cause| !cause.contains("timed out"));
                    }

                    #[cfg(not(feature = "linkcheck"))]
                    {
                        false
                    }
                };

                if actually_broken {
                    std::process::exit(101);
                } else {
                    std::process::exit(0);
                }
            }
        }
        (_, _) => unreachable!(),
    };
}

#[cfg(feature = "linkcheck")]
pub fn linkcheck(args: &ArgMatches<'_>) -> Result<(), Error> {
    let book_dir = get_book_dir(args);
    let book = MDBook::load(&book_dir).unwrap();
    let cfg = book.config;
    let render_ctx = RenderContext::new(&book_dir, book.book, cfg, &book_dir);

    mdbook_linkcheck::check_links(&render_ctx)
}

#[cfg(not(feature = "linkcheck"))]
pub fn linkcheck(_args: &ArgMatches<'_>) -> Result<(), Error> {
    println!("mdbook-linkcheck is disabled.");
    Ok(())
}

// Build command implementation
pub fn build(args: &ArgMatches<'_>) -> Result3<()> {
    let book_dir = get_book_dir(args);
    let mut book = MDBook::load(&book_dir)?;

    // Set this to allow us to catch bugs in advance.
    book.config.build.create_missing = false;

    if let Some(dest_dir) = args.value_of("dest-dir") {
        book.config.build.build_dir = PathBuf::from(dest_dir);
    }

    book.build()?;

    Ok(())
}

fn get_book_dir(args: &ArgMatches<'_>) -> PathBuf {
    if let Some(dir) = args.value_of("dir") {
        // Check if path is relative from current dir, or absolute...
        let p = Path::new(dir);
        if p.is_relative() {
            env::current_dir().unwrap().join(dir)
        } else {
            p.to_path_buf()
        }
    } else {
        env::current_dir().unwrap()
    }
}
<|endoftext|>


<commit_before>//! Plugin which transforms `dc::File` to point at local clones of GitHub
//! repositories.

use compose_yml::v2 as dc;
use std::marker::PhantomData;

use errors::*;
use ext::service::ServiceExt;
use plugins;
use plugins::{Operation, PluginNew, PluginTransform};
use project::Project;
use util::ConductorPathExt;

/// Transforms `dc::File` to point at local clones of GitHub repositories.
///
/// Note that this is only part of our repository support—this plugin
/// doesn't load repositories or check them out.  (That's the job of our
/// top-level `repos` module.)  Rather, this plugin uses information that
/// we already know about repositories in order to transform a `dc::File`
/// for local development purposes.
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub struct Plugin {
    /// Placeholder field for future hidden fields, to keep this from being
    /// directly constructable.
    _placeholder: PhantomData<()>,
}

impl plugins::Plugin for Plugin {
    fn name(&self) -> &'static str {
        Self::plugin_name()
    }
}

impl PluginNew for Plugin {
    fn plugin_name() -> &'static str {
        "repos"
    }

    fn new(_project: &Project) -> Result<Self> {
        Ok(Plugin { _placeholder: PhantomData })
    }
}

impl PluginTransform for Plugin {
    fn transform(&self,
                 op: Operation,
                 ctx: &plugins::Context,
                 file: &mut dc::File)
                 -> Result<()> {
        // Give up immediately if we're not doing this for local output.
        if op != Operation::Output {
            return Ok(());
        }

        // Update each service to point to our locally cloned repos.
        let project = ctx.project;
        for service in &mut file.services.values_mut() {

            // Handle the main repo associated with this service.
            if let Some(git_url) = try!(service.git_url()).cloned() {
                if let Some(repo) = project.repos().find_by_git_url(&git_url) {
                    if repo.is_cloned(project) {
                        // Build an absolute path to our repo's clone directory.
                        let path = try!(repo.path(project).to_absolute());

                        // Mount the local build directory inside the
                        // container.
                        let srcdir = try!(service.source_mount_dir());
                        let mount = dc::VolumeMount::host(&path, &srcdir);
                        service.volumes.push(dc::value(mount));

                        // Update the `build` field if present.
                        if let Some(ref mut build) = service.build {
                            build.context = dc::value(dc::Context::Dir(path));
                        }
                    }
                }
            }

            // Look for library repos as well.
            for (label, mount_as) in &service.labels {
                let prefix = "io.fdy.cage.lib.";
                if label.starts_with(prefix) {
                    let key = &label[prefix.len()..];
                    let repo = try!(project.repos()
                        .find_by_lib_key(key)
                        .ok_or_else(|| {
                            err!("no library <{}> defined in `config/libraries.yml`",
                                 key)
                        }));

                    let path = try!(repo.path(project).to_absolute());
                    let mount = dc::VolumeMount::host(&path, mount_as);
                    service.volumes.push(dc::value(mount));
                }
            }
        }

        Ok(())
    }
}
<commit_msg>Do not mount libraries into containers unless they're cloned locally<commit_after>//! Plugin which transforms `dc::File` to point at local clones of GitHub
//! repositories.

use compose_yml::v2 as dc;
use std::marker::PhantomData;

use errors::*;
use ext::service::ServiceExt;
use plugins;
use plugins::{Operation, PluginNew, PluginTransform};
use project::Project;
use util::ConductorPathExt;

/// Transforms `dc::File` to point at local clones of GitHub repositories.
///
/// Note that this is only part of our repository support—this plugin
/// doesn't load repositories or check them out.  (That's the job of our
/// top-level `repos` module.)  Rather, this plugin uses information that
/// we already know about repositories in order to transform a `dc::File`
/// for local development purposes.
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub struct Plugin {
    /// Placeholder field for future hidden fields, to keep this from being
    /// directly constructable.
    _placeholder: PhantomData<()>,
}

impl plugins::Plugin for Plugin {
    fn name(&self) -> &'static str {
        Self::plugin_name()
    }
}

impl PluginNew for Plugin {
    fn plugin_name() -> &'static str {
        "repos"
    }

    fn new(_project: &Project) -> Result<Self> {
        Ok(Plugin { _placeholder: PhantomData })
    }
}

impl PluginTransform for Plugin {
    fn transform(&self,
                 op: Operation,
                 ctx: &plugins::Context,
                 file: &mut dc::File)
                 -> Result<()> {
        // Give up immediately if we're not doing this for local output.
        if op != Operation::Output {
            return Ok(());
        }

        // Update each service to point to our locally cloned repos.
        let project = ctx.project;
        for service in &mut file.services.values_mut() {

            // Handle the main repo associated with this service.
            if let Some(git_url) = try!(service.git_url()).cloned() {
                if let Some(repo) = project.repos().find_by_git_url(&git_url) {
                    if repo.is_cloned(project) {
                        // Build an absolute path to our repo's clone directory.
                        let path = try!(repo.path(project).to_absolute());

                        // Mount the local build directory inside the
                        // container.
                        let srcdir = try!(service.source_mount_dir());
                        let mount = dc::VolumeMount::host(&path, &srcdir);
                        service.volumes.push(dc::value(mount));

                        // Update the `build` field if present.
                        if let Some(ref mut build) = service.build {
                            build.context = dc::value(dc::Context::Dir(path));
                        }
                    }
                }
            }

            // Look for library repos as well.
            for (label, mount_as) in &service.labels {
                let prefix = "io.fdy.cage.lib.";
                if label.starts_with(prefix) {
                    let key = &label[prefix.len()..];
                    let repo = try!(project.repos()
                        .find_by_lib_key(key)
                        .ok_or_else(|| {
                            err!("no library <{}> defined in `config/libraries.yml`",
                                 key)
                        }));

                    if repo.is_cloned(project) {
                        let path = try!(repo.path(project).to_absolute());
                        let mount = dc::VolumeMount::host(&path, mount_as);
                        service.volumes.push(dc::value(mount));
                    }
                }
            }
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>// !
// Resource caching smart pointer
//

extern crate serde;

use std::rc::Rc;
use std::ops::Deref;
use std::hash;
use std::collections::HashMap;
use std::fmt;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

/// A type that implements a singleton resource store.
pub trait ResourceStore<K = String> {
    fn get_resource(key: &K) -> Option<Rc<Self>> where Self: Sized;

    fn insert_resource(key: K, resource: Self);
}

/// Smart pointer for an immutable cached resource.
///
/// The semantics are similar to Rc pointers.
///
/// Resource values will serialize as their key values, so they can be attached to structures that
/// require compact serialization.
#[derive(Clone)]
pub struct Resource<T, K = String> {
    handle: Rc<T>,
    key: K,
}

impl<T: Sized, K> AsRef<T> for Resource<T, K> {
    fn as_ref(&self) -> &T {
        self.handle.as_ref()
    }
}

impl<T: Sized, K> Deref for Resource<T, K> {
    type Target = T;

    #[inline(always)]
    fn deref(&self) -> &T {
        self.handle.deref()
    }
}

impl<T> Serialize for Resource<T> {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        self.key.serialize(serializer)
    }
}

impl<T: ResourceStore> Deserialize for Resource<T> {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer
    {
        let key: String = try!(Deserialize::deserialize(deserializer));
        Ok(Self::new(key).unwrap())
    }
}

impl<T, K: hash::Hash> hash::Hash for Resource<T, K> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.key.hash(state);
    }
}

impl<T, K: PartialEq> PartialEq for Resource<T, K> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}

impl<T, K: Eq> Eq for Resource<T, K> {}

impl<T, K: fmt::Display> fmt::Display for Resource<T, K> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.key.fmt(formatter)
    }
}

impl<T, K: fmt::Debug> fmt::Debug for Resource<T, K> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.key.fmt(formatter)
    }
}

impl<K, T: ResourceStore<K>> Resource<T, K> {
    pub fn new(key: K) -> Option<Self> {
        if let Some(handle) = ResourceStore::get_resource(&key) {
            Some(Resource {
                handle: handle,
                key: key,
            })
        } else {
            None
        }
    }
}

/// A cache that associates resource values with paths.
///
/// Resources and paths are assumed to be immutable.
pub struct ResourceCache<T, K = String> {
    cache: HashMap<K, Rc<T>>,
}

impl<K: Eq + hash::Hash + Clone, T> ResourceCache<T, K> {
    pub fn new() -> ResourceCache<T, K> {
        ResourceCache { cache: HashMap::new() }
    }

    pub fn get(&mut self, key: &K) -> Option<Rc<T>> {
        self.cache.get(key).map(|x| x.clone())
    }

    pub fn insert(&mut self, key: K, value: T) {
        self.cache.insert(key, Rc::new(value));
    }
}

/// Implement a thread-local store for a given resource type.
///
/// Name is the identifier for the store, key and value are the types of the resource cache keys
/// and the resources.
///
///     # #[macro_use] extern crate calx_resource;
///     use calx_resource::{Resource, ResourceStore};
///
///     // A custom resource type.
///     struct MyResource { pub text: String }
///
///     // Generate a resource store.
///     impl_store!(MY_RESOURCE_STORE, String, MyResource);
///
///     fn main() {
///         // Save a resource in the store using a key.
///         MyResource::insert_resource(
///             "test_resource".to_string(),
///             MyResource { text: "Hello, world!".to_string() });
///
///         // Fetch a resource handle from the store using our key.
///         let handle: Resource<MyResource> =
///             Resource::new("test_resource".to_string()).unwrap();
///         assert!(&handle.text == "Hello, world!");
///     }
#[macro_export]
macro_rules! impl_store {
    ($name:ident, $key:ty, $value:ty) => {
    thread_local!(static $name: ::std::cell::RefCell<$crate::ResourceCache<$value, $key>> =
                  ::std::cell::RefCell::new($crate::ResourceCache::new()));

    impl $crate::ResourceStore<$key> for $value {
        fn get_resource(key: &$key) -> Option<::std::rc::Rc<Self>> {
            $name.with(|t| t.borrow_mut().get(key))
        }

        fn insert_resource(key: $key, value: $value) {
            $name.with(|t| t.borrow_mut().insert(key, value));
        }
    }}
}
<commit_msg>Add Loadable trait to Resource<commit_after>// !
// Resource caching smart pointer
//

extern crate serde;

use std::rc::Rc;
use std::ops::Deref;
use std::hash;
use std::collections::HashMap;
use std::fmt;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

/// A type that implements a singleton resource store.
pub trait ResourceStore<K = String> {
    fn get_resource(key: &K) -> Option<Rc<Self>> where Self: Sized;

    fn insert_resource(key: K, resource: Self);
}

/// Smart pointer for an immutable cached resource.
///
/// The semantics are similar to Rc pointers.
///
/// Resource values will serialize as their key values, so they can be attached to structures that
/// require compact serialization.
#[derive(Clone)]
pub struct Resource<T, K = String> {
    handle: Rc<T>,
    key: K,
}

impl<T: Sized, K> AsRef<T> for Resource<T, K> {
    fn as_ref(&self) -> &T {
        self.handle.as_ref()
    }
}

impl<T: Sized, K> Deref for Resource<T, K> {
    type Target = T;

    #[inline(always)]
    fn deref(&self) -> &T {
        self.handle.deref()
    }
}

impl<T> Serialize for Resource<T> {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        self.key.serialize(serializer)
    }
}

impl<T: ResourceStore> Deserialize for Resource<T> {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer
    {
        let key: String = try!(Deserialize::deserialize(deserializer));
        Ok(Self::new(key).unwrap())
    }
}

impl<T, K: hash::Hash> hash::Hash for Resource<T, K> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.key.hash(state);
    }
}

impl<T, K: PartialEq> PartialEq for Resource<T, K> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}

impl<T, K: Eq> Eq for Resource<T, K> {}

impl<T, K: fmt::Display> fmt::Display for Resource<T, K> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.key.fmt(formatter)
    }
}

impl<T, K: fmt::Debug> fmt::Debug for Resource<T, K> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.key.fmt(formatter)
    }
}

impl<K, T: ResourceStore<K>> Resource<T, K> {
    pub fn new(key: K) -> Option<Self> {
        if let Some(handle) = ResourceStore::get_resource(&key) {
            Some(Resource {
                handle: handle,
                key: key,
            })
        } else {
            None
        }
    }
}

/// A value that can be implicitly constructed given a key.
pub trait Loadable<K = String> {
    fn load(_key: &K) -> Option<Self>
        where Self: Sized
    {
        // Default implementation so that types with no load semantics can be used with
        // ResourceCache so that all inserts must be explicit.
        None
    }
}

/// A cache that associates resource values with paths.
///
/// Resources and paths are assumed to be immutable.
pub struct ResourceCache<T, K = String> {
    cache: HashMap<K, Rc<T>>,
}

impl<K: Eq + hash::Hash + Clone, T: Loadable<K>> ResourceCache<T, K> {
    pub fn new() -> ResourceCache<T, K> {
        ResourceCache { cache: HashMap::new() }
    }

    pub fn get(&mut self, key: &K) -> Option<Rc<T>> {
        if let Some(v) = self.cache.get(key) {
            return Some(v.clone());
        }

        if let Some(v) = T::load(key) {
            let v = Rc::new(v);
            self.cache.insert(key.clone(), v.clone());
            Some(v)
        } else {
            None
        }
    }

    pub fn insert(&mut self, key: K, value: T) {
        self.cache.insert(key, Rc::new(value));
    }
}

/// Implement a thread-local store for a given resource type.
///
/// Name is the identifier for the store, key and value are the types of the resource cache keys
/// and the resources.
///
///     # #[macro_use] extern crate calx_resource;
///     use calx_resource::{Resource, ResourceStore, Loadable};
///
///     // A custom resource type.
///     struct MyResource { pub text: String }
///
///     // Must be present even if there's no specific implementation.
///     impl Loadable for MyResource {}
///
///     // Generate a resource store.
///     impl_store!(MY_RESOURCE_STORE, String, MyResource);
///
///     fn main() {
///         // Save a resource in the store using a key.
///         MyResource::insert_resource(
///             "test_resource".to_string(),
///             MyResource { text: "Hello, world!".to_string() });
///
///         // Fetch a resource handle from the store using our key.
///         let handle: Resource<MyResource> =
///             Resource::new("test_resource".to_string()).unwrap();
///         assert!(&handle.text == "Hello, world!");
///     }
#[macro_export]
macro_rules! impl_store {
    ($name:ident, $key:ty, $value:ty) => {
    thread_local!(static $name: ::std::cell::RefCell<$crate::ResourceCache<$value, $key>> =
                  ::std::cell::RefCell::new($crate::ResourceCache::new()));

    impl $crate::ResourceStore<$key> for $value {
        fn get_resource(key: &$key) -> Option<::std::rc::Rc<Self>> {
            $name.with(|t| t.borrow_mut().get(key))
        }

        fn insert_resource(key: $key, value: $value) {
            $name.with(|t| t.borrow_mut().insert(key, value));
        }
    }}
}
<|endoftext|>


<commit_before>fn generate_table () {
    let pi: f64 = 3.1415926536897932384626;
    let k1: f64 = 0.6072529350088812561694; // 1/k
    let num_bits: uint = 32;
    //let num_elms: uint = num_bits;
    let mul: uint = 1<<(num_bits-2);

    println!("Cordic sin in rust");
    println!("num bits {}", num_bits);
    println!("mul {}", mul);
    println!("1<<(num_bits-2) {}", ((1i << (num_bits-2)) as f64));
    println!("pi is {}", pi);
    println!("k1 is {}", k1);

    println!("let cordic_tab = [");

    let shift: f64 = 2.0;
    for ii in range(0, num_bits) {
        let ipow: f64 = 1f64/shift.powi(ii as i32);
        let cur: f64 = ipow.atan() * (mul as f64);

        if ii % 4 == 0 && ii > 0 {
            println!("");
        }
        if ii == 0 {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        } else {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        }
    }

    println!("];");
}

fn int_to_f64 (lhs: int) -> f64 {
    let rhs: f64 = unsafe {
        std::mem::transmute(lhs)
    };
    return rhs;
}

fn f64_to_int (lhs: f64) -> int {
    let rhs: int = unsafe {
        std::mem::transmute(lhs)
    };
    return rhs;
}

fn sin(theta: f64) {

    let num_bits: uint = 32;

    let k1: int = f64_to_int(0.6072529350088812561694); // 1/k
    let mul: int = 1<<(num_bits-2);
    let mut x: int = mul * k1;
    let mut y: int = 0;
    let mut z: int = f64_to_int(theta);
    let mut tx: int;
    let mut ty: int ;
    let mut tz: int;

    let mut d: int;

    println!("x {}", x);

    let cordic_tab = [
        0x3243f6a8, 0x1dac6705, 0xfadbafc, 0x7f56ea6,
        0x3feab76, 0x1ffd55b, 0xfffaaa, 0x7fff55,
        0x3fffea, 0x1ffffd, 0xfffff, 0x7ffff,
        0x3ffff, 0x1ffff, 0xffff, 0x7fff,
        0x3fff, 0x1fff, 0xfff, 0x7ff,
        0x3ff, 0x1ff, 0xff, 0x7f,
        0x3f, 0x1f, 0xf, 0x8,
        0x4, 0x2, 0x1, 0x0, ];

    for k in range(0, num_bits) {
        if z >= 0 {
            d = 0;
        } else {
            d = -1;
        }
        tx = x - (((y>>k) ^ d) - d);
        ty = y + (((x>>k) ^ d) - d);
        tz = z - ((cordic_tab[k] ^ d) - d);
        x = tx;
        y = ty;
        z = tz;

        println!("{}", k);
        println!("{}", int_to_f64(tx));
    }
}

fn main() {
    let i: int = 42882;
    let f: f64 = 3498043.4824;
    assert!(int_to_f64(f64_to_int(f)) == f);
    assert!(f64_to_int(int_to_f64(i)) == i);

    generate_table();
    sin(0.5);
}
<commit_msg>does iteration calculations<commit_after>
fn generate_table () {

    let pi: f64 = 3.1415926536897932384626;
    let k1: f64 = 0.6072529350088812561694; // 1/k
    let num_bits: uint = 32;
    //let num_elms: uint = num_bits;
    let mul: uint = 1<<(num_bits-2);

    println!("Cordic sin in rust");
    println!("num bits {}", num_bits);
    println!("mul {}", mul);
    println!("1<<(num_bits-2) {}", ((1i << (num_bits-2)) as f64));
    println!("pi is {}", pi);
    println!("k1 is {}", k1);

    println!("let cordic_tab = [");

    let shift: f64 = 2.0;
    for ii in range(0, num_bits) {
        let ipow: f64 = 1f64/shift.powi(ii as i32);
        let cur: f64 = ipow.atan() * (mul as f64);

        if ii % 4 == 0 && ii > 0 {
            println!("");
        }
        if ii == 0 {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        } else {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        }
    }

    println!("];");
}

fn int_to_f64 (lhs: int) -> f64 {
    let rhs: f64 = unsafe {
        std::mem::transmute(lhs)
    };
    return rhs;
}

fn f64_to_int (lhs: f64) -> int {
    let rhs: int = unsafe {
        std::mem::transmute(lhs)
    };
    return rhs;
}

fn sin(theta: f64) {

    let num_bits: uint = 32;

    //let k1: int = f64_to_int(0.6072529350088812561694); // 1/k
    //let mul: int = 1<<(num_bits-2);
    let mut x: int = 0x26DD3B6A; // todo derive this k1 and mul
    let mut y: int = 0;
    let mut z: int = theta.floor() as int;
    let mut tx: int;
    let mut ty: int ;
    let mut tz: int;

    let mut d: int;
    let cordic_tab = [
        0x3243f6a8, 0x1dac6705, 0xfadbafc, 0x7f56ea6,
        0x3feab76, 0x1ffd55b, 0xfffaaa, 0x7fff55,
        0x3fffea, 0x1ffffd, 0xfffff, 0x7ffff,
        0x3ffff, 0x1ffff, 0xffff, 0x7fff,
        0x3fff, 0x1fff, 0xfff, 0x7ff,
        0x3ff, 0x1ff, 0xff, 0x7f,
        0x3f, 0x1f, 0xf, 0x8,
        0x4, 0x2, 0x1, 0x0, ];

    for k in range(0, num_bits) {
        if z >= 0 {
            d = 0;
        } else {
            d = -1;
        }

        println!("z {}", z);

        tx = x - (((y>>k) ^ d) - d);
        ty = y + (((x>>k) ^ d) - d);
        tz = z - ((cordic_tab[k] ^ d) - d);
        println!("{} {} {} {} {} {}", k, x, y, tx, ty, tz);
        x = tx; y = ty; z = tz;
    }
}

fn main() {
    let i: int = 42882;
    let f: f64 = 3498043.4824;
    assert!(int_to_f64(f64_to_int(f)) == f);
    assert!(f64_to_int(int_to_f64(i)) == i);

    generate_table();

    let theta: f64 = 33732594.261305;
    sin(theta);
}
<|endoftext|>


<commit_before>#![warn(bad_style)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
// #![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate ansi_term;
extern crate argparse;
extern crate slsr_core;
extern crate slsr_solver;

use std::{io, process};
use std::fs::File;
use std::io::prelude::*;

use slsr_core::puzzle::Puzzle;
use slsr_solver::{self as solver, Solutions};

use error::AppResult;
use parse_arg::{Config, OutputMode, SolveConfig};

mod error;
mod parse_arg;
mod pprint;

fn output(config: &SolveConfig, solution: Puzzle) -> io::Result<()> {
    match config.output_mode {
        OutputMode::Pretty(conf) => {
            try!(pprint::print(&conf, &solution));
        }
        OutputMode::Raw => {
            print!("{}", solution.to_string());
        }
        OutputMode::None => {}
    }

    Ok(())
}

fn solve<T: Read>(config: &SolveConfig, input: &mut T) -> AppResult<()> {
    let mut buf = String::new();
    let _ = try!(input.read_to_string(&mut buf));
    let puzzle = try!(buf.parse::<Puzzle>());

    if config.derive_all {
        for solution in try!(Solutions::new(&puzzle)) {
            try!(output(&config, solution));
        }
    } else {
        let solution = try!(solver::solve(&puzzle));
        try!(output(&config, solution));
    }

    Ok(())
}

fn run() -> AppResult<()> {
    match Config::parse() {
        Config::Solve(config) => {
            if config.input_files.is_empty() {
                try!(solve(&config, &mut io::stdin()));
            } else {
                for file in &config.input_files {
                    let mut f = try!(File::open(file));
                    try!(solve(&config, &mut f));
                }
            }
        }
    }

    Ok(())
}

fn main() {
    if let Err(e) = run() {
        let _ = writeln!(&mut io::stderr(), "{}", e);
        process::exit(255);
    }
}
<commit_msg>cli: extract solve module<commit_after>#![warn(bad_style)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
// #![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate ansi_term;
extern crate argparse;
extern crate slsr_core;
extern crate slsr_solver;

use std::{io, process};
use std::io::prelude::*;

use error::AppResult;
use parse_arg::Config;

mod error;
mod parse_arg;
mod pprint;

mod solve {
    use std::io;
    use std::fs::File;
    use std::io::prelude::*;

    use slsr_core::puzzle::Puzzle;
    use slsr_solver::{self as solver, Solutions};

    use error::AppResult;
    use parse_arg::{OutputMode, SolveConfig};
    use pprint;

    pub fn run(config: SolveConfig) -> AppResult<()> {
        if config.input_files.is_empty() {
            try!(solve(&config, &mut io::stdin()));
        } else {
            for file in &config.input_files {
                let mut f = try!(File::open(file));
                try!(solve(&config, &mut f));
            }
        }

        Ok(())
    }

    fn solve<T: Read>(config: &SolveConfig, input: &mut T) -> AppResult<()> {
        let mut buf = String::new();
        let _ = try!(input.read_to_string(&mut buf));
        let puzzle = try!(buf.parse::<Puzzle>());

        if config.derive_all {
            for solution in try!(Solutions::new(&puzzle)) {
                try!(output(&config, solution));
            }
        } else {
            let solution = try!(solver::solve(&puzzle));
            try!(output(&config, solution));
        }

        Ok(())
    }

    fn output(config: &SolveConfig, solution: Puzzle) -> io::Result<()> {
        match config.output_mode {
            OutputMode::Pretty(conf) => {
                try!(pprint::print(&conf, &solution));
            }
            OutputMode::Raw => {
                print!("{}", solution.to_string());
            }
            OutputMode::None => {}
        }

        Ok(())
    }
}

fn run() -> AppResult<()> {
    match Config::parse() {
        Config::Solve(config) => solve::run(config),
    }
}

fn main() {
    if let Err(e) = run() {
        let _ = writeln!(&mut io::stderr(), "{}", e);
        process::exit(255);
    }
}
<|endoftext|>


<commit_before>// min-llvm-version: 10.0.1
// only-aarch64
// only-linux
// run-pass

#![feature(asm, thread_local)]

extern "C" fn f1() -> i32 {
    111
}

// The compiler will generate a shim to hide the caller location parameter.
#[track_caller]
fn f2() -> i32 {
    222
}

macro_rules! call {
    ($func:path) => {
        unsafe {
            let result: i32;
            asm!("bl {}", sym $func,
                out("w0") result,
                out("x20") _, out("x21") _, out("x22") _,
                out("x23") _, out("x24") _, out("x25") _,
                out("x26") _, out("x27") _, out("x28") _,
            );
            result
        }
    }
}

macro_rules! static_addr {
    ($s:expr) => {
        unsafe {
            let result: *const u32;
            asm!(
                // ADRP gives the address of a 4KB page from a PC-relative address
                "adrp {out}, {sym}",
                // We then add the remaining lower 12 bits
                "add {out}, {out}, #:lo12:{sym}",
                out = out(reg) result,
                sym = sym $s);
            result
        }
    }
}
macro_rules! static_tls_addr {
    ($s:expr) => {
        unsafe {
            let result: *const u32;
            asm!(
                // Load the thread pointer register
                "mrs {out}, TPIDR_EL0",
                // Add the top 12 bits of the symbol's offset
                "add {out}, {out}, :tprel_hi12:{sym}",
                // And the bottom 12 bits
                "add {out}, {out}, :tprel_lo12:{sym}",
                out = out(reg) result,
                sym = sym $s
            );
            result
        }
    }
}

static S1: u32 = 111;
#[thread_local]
static S2: u32 = 222;

fn main() {
    assert_eq!(call!(f1), 111);
    assert_eq!(call!(f2), 222);
    assert_eq!(static_addr!(S1), &S1 as *const u32);
    assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
    std::thread::spawn(|| {
        assert_eq!(static_addr!(S1), &S1 as *const u32);
        assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
    }).join().unwrap();
}
<commit_msg>Use non-checking TLS relocation in aarch64 asm! sym test.<commit_after>// min-llvm-version: 10.0.1
// only-aarch64
// only-linux
// run-pass

#![feature(asm, thread_local)]

extern "C" fn f1() -> i32 {
    111
}

// The compiler will generate a shim to hide the caller location parameter.
#[track_caller]
fn f2() -> i32 {
    222
}

macro_rules! call {
    ($func:path) => {
        unsafe {
            let result: i32;
            asm!("bl {}", sym $func,
                out("w0") result,
                out("x20") _, out("x21") _, out("x22") _,
                out("x23") _, out("x24") _, out("x25") _,
                out("x26") _, out("x27") _, out("x28") _,
            );
            result
        }
    }
}

macro_rules! static_addr {
    ($s:expr) => {
        unsafe {
            let result: *const u32;
            asm!(
                // ADRP gives the address of a 4KB page from a PC-relative address
                "adrp {out}, {sym}",
                // We then add the remaining lower 12 bits
                "add {out}, {out}, #:lo12:{sym}",
                out = out(reg) result,
                sym = sym $s);
            result
        }
    }
}
macro_rules! static_tls_addr {
    ($s:expr) => {
        unsafe {
            let result: *const u32;
            asm!(
                // Load the thread pointer register
                "mrs {out}, TPIDR_EL0",
                // Add the top 12 bits of the symbol's offset
                "add {out}, {out}, :tprel_hi12:{sym}",
                // And the bottom 12 bits
                "add {out}, {out}, :tprel_lo12_nc:{sym}",
                out = out(reg) result,
                sym = sym $s
            );
            result
        }
    }
}

static S1: u32 = 111;
#[thread_local]
static S2: u32 = 222;

fn main() {
    assert_eq!(call!(f1), 111);
    assert_eq!(call!(f2), 222);
    assert_eq!(static_addr!(S1), &S1 as *const u32);
    assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
    std::thread::spawn(|| {
        assert_eq!(static_addr!(S1), &S1 as *const u32);
        assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
    }).join().unwrap();
}
<|endoftext|>


<commit_before>use crate::utils::sugg::Sugg;
use crate::utils::{
    differing_macro_contexts, is_type_diagnostic_item, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty,
    SpanlessEq,
};
use if_chain::if_chain;
use matches::matches;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty;
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use syntax_pos::Symbol;

declare_clippy_lint! {
    /// **What it does:** Checks for manual swapping.
    ///
    /// **Why is this bad?** The `std::mem::swap` function exposes the intent better
    /// without deinitializing or copying either variable.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// let mut a = 42;
    /// let mut b = 1337;
    ///
    /// let t = b;
    /// b = a;
    /// a = t;
    /// ```
    /// Use std::mem::swap():
    /// ```rust
    /// let mut a = 1;
    /// let mut b = 2;
    /// std::mem::swap(&mut a, &mut b);
    /// ```
    pub MANUAL_SWAP,
    complexity,
    "manual swap of two variables"
}

declare_clippy_lint! {
    /// **What it does:** Checks for `foo = bar; bar = foo` sequences.
    ///
    /// **Why is this bad?** This looks like a failed attempt to swap.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// # let mut a = 1;
    /// # let mut b = 2;
    /// a = b;
    /// b = a;
    /// ```
    /// Could be written as:
    /// ```rust
    /// # let mut a = 1;
    /// # let mut b = 2;
    /// std::mem::swap(&mut a, &mut b);
    /// ```
    pub ALMOST_SWAPPED,
    correctness,
    "`foo = bar; bar = foo` sequence"
}

declare_lint_pass!(Swap => [MANUAL_SWAP, ALMOST_SWAPPED]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Swap {
    fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx Block) {
        check_manual_swap(cx, block);
        check_suspicious_swap(cx, block);
    }
}

/// Implementation of the `MANUAL_SWAP` lint.
fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) {
    for w in block.stmts.windows(3) {
        if_chain! {
            // let t = foo();
            if let StmtKind::Local(ref tmp) = w[0].kind;
            if let Some(ref tmp_init) = tmp.init;
            if let PatKind::Binding(.., ident, None) = tmp.pat.kind;

            // foo() = bar();
            if let StmtKind::Semi(ref first) = w[1].kind;
            if let ExprKind::Assign(ref lhs1, ref rhs1) = first.kind;

            // bar() = t;
            if let StmtKind::Semi(ref second) = w[2].kind;
            if let ExprKind::Assign(ref lhs2, ref rhs2) = second.kind;
            if let ExprKind::Path(QPath::Resolved(None, ref rhs2)) = rhs2.kind;
            if rhs2.segments.len() == 1;

            if ident.as_str() == rhs2.segments[0].ident.as_str();
            if SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1);
            if SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2);
            then {
                if let ExprKind::Field(ref lhs1, _) = lhs1.kind {
                    if let ExprKind::Field(ref lhs2, _) = lhs2.kind {
                        if lhs1.hir_id.owner_def_id() == lhs2.hir_id.owner_def_id() {
                            return;
                        }
                    }
                }

                let slice = check_for_slice(cx, lhs1, lhs2);

                let (replace, what, sugg) = if let Slice::NotSwappable = slice {
                    return;
                } else if let Slice::Swappable(slice, idx1, idx2) = slice {
                    if let Some(slice) = Sugg::hir_opt(cx, slice) {
                        (false,
                         format!(" elements of `{}`", slice),
                         format!("{}.swap({}, {})",
                                 slice.maybe_par(),
                                 snippet(cx, idx1.span, ".."),
                                 snippet(cx, idx2.span, "..")))
                    } else {
                        (false, String::new(), String::new())
                    }
                } else if let (Some(first), Some(second)) = (Sugg::hir_opt(cx, lhs1), Sugg::hir_opt(cx, rhs1)) {
                    (true, format!(" `{}` and `{}`", first, second),
                        format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr()))
                } else {
                    (true, String::new(), String::new())
                };

                let span = w[0].span.to(second.span);

                span_lint_and_then(cx,
                                   MANUAL_SWAP,
                                   span,
                                   &format!("this looks like you are swapping{} manually", what),
                                   |db| {
                                       if !sugg.is_empty() {
                                           db.span_suggestion(
                                               span,
                                               "try",
                                               sugg,
                                               Applicability::Unspecified,
                                           );

                                           if replace {
                                               db.note("or maybe you should use `std::mem::replace`?");
                                           }
                                       }
                                   });
            }
        }
    }
}

enum Slice<'a> {
    /// `slice.swap(idx1, idx2)` can be used
    ///
    /// ## Example
    ///
    /// ```rust
    /// let t = a[1];
    /// a[1] = a[0];
    /// a[0] = t;
    /// // can be written as
    /// a.swap(0, 1);
    /// ```
    Swappable(&'a Expr, &'a Expr, &'a Expr),
    /// The `swap` function cannot be used.
    ///
    /// ## Example
    ///
    /// ```rust
    /// let t = a[0][1];
    /// a[0][1] = a[1][0];
    /// a[1][0] = t;
    /// ```
    NotSwappable,
    /// Not a slice
    None,
}

/// Checks if both expressions are index operations into "slice-like" types.
fn check_for_slice<'a>(cx: &LateContext<'_, '_>, lhs1: &'a Expr, lhs2: &'a Expr) -> Slice<'a> {
    if let ExprKind::Index(ref lhs1, ref idx1) = lhs1.kind {
        if let ExprKind::Index(ref lhs2, ref idx2) = lhs2.kind {
            if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) {
                let ty = walk_ptrs_ty(cx.tables.expr_ty(lhs1));

                if matches!(ty.kind, ty::Slice(_))
                    || matches!(ty.kind, ty::Array(_, _))
                    || is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type"))
                    || match_type(cx, ty, &paths::VEC_DEQUE)
                {
                    return Slice::Swappable(lhs1, idx1, idx2);
                }
            } else {
                return Slice::NotSwappable;
            }
        }
    }

    Slice::None
}

/// Implementation of the `ALMOST_SWAPPED` lint.
fn check_suspicious_swap(cx: &LateContext<'_, '_>, block: &Block) {
    for w in block.stmts.windows(2) {
        if_chain! {
            if let StmtKind::Semi(ref first) = w[0].kind;
            if let StmtKind::Semi(ref second) = w[1].kind;
            if !differing_macro_contexts(first.span, second.span);
            if let ExprKind::Assign(ref lhs0, ref rhs0) = first.kind;
            if let ExprKind::Assign(ref lhs1, ref rhs1) = second.kind;
            if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs0, rhs1);
            if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, rhs0);
            then {
                let lhs0 = Sugg::hir_opt(cx, lhs0);
                let rhs0 = Sugg::hir_opt(cx, rhs0);
                let (what, lhs, rhs) = if let (Some(first), Some(second)) = (lhs0, rhs0) {
                    (
                        format!(" `{}` and `{}`", first, second),
                        first.mut_addr().to_string(),
                        second.mut_addr().to_string(),
                    )
                } else {
                    (String::new(), String::new(), String::new())
                };

                let span = first.span.to(second.span);

                span_lint_and_then(cx,
                                   ALMOST_SWAPPED,
                                   span,
                                   &format!("this looks like you are trying to swap{}", what),
                                   |db| {
                                       if !what.is_empty() {
                                           db.span_suggestion(
                                               span,
                                               "try",
                                               format!(
                                                   "std::mem::swap({}, {})",
                                                   lhs,
                                                   rhs,
                                               ),
                                               Applicability::MaybeIncorrect,
                                           );
                                           db.note("or maybe you should use `std::mem::replace`?");
                                       }
                                   });
            }
        }
    }
}
<commit_msg>Formatting<commit_after>use crate::utils::sugg::Sugg;
use crate::utils::{
    differing_macro_contexts, is_type_diagnostic_item, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty,
    SpanlessEq,
};
use if_chain::if_chain;
use matches::matches;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty;
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use syntax_pos::Symbol;

declare_clippy_lint! {
    /// **What it does:** Checks for manual swapping.
    ///
    /// **Why is this bad?** The `std::mem::swap` function exposes the intent better
    /// without deinitializing or copying either variable.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// let mut a = 42;
    /// let mut b = 1337;
    ///
    /// let t = b;
    /// b = a;
    /// a = t;
    /// ```
    /// Use std::mem::swap():
    /// ```rust
    /// let mut a = 1;
    /// let mut b = 2;
    /// std::mem::swap(&mut a, &mut b);
    /// ```
    pub MANUAL_SWAP,
    complexity,
    "manual swap of two variables"
}

declare_clippy_lint! {
    /// **What it does:** Checks for `foo = bar; bar = foo` sequences.
    ///
    /// **Why is this bad?** This looks like a failed attempt to swap.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// # let mut a = 1;
    /// # let mut b = 2;
    /// a = b;
    /// b = a;
    /// ```
    /// Could be written as:
    /// ```rust
    /// # let mut a = 1;
    /// # let mut b = 2;
    /// std::mem::swap(&mut a, &mut b);
    /// ```
    pub ALMOST_SWAPPED,
    correctness,
    "`foo = bar; bar = foo` sequence"
}

declare_lint_pass!(Swap => [MANUAL_SWAP, ALMOST_SWAPPED]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Swap {
    fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx Block) {
        check_manual_swap(cx, block);
        check_suspicious_swap(cx, block);
    }
}

/// Implementation of the `MANUAL_SWAP` lint.
fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) {
    for w in block.stmts.windows(3) {
        if_chain! {
            // let t = foo();
            if let StmtKind::Local(ref tmp) = w[0].kind;
            if let Some(ref tmp_init) = tmp.init;
            if let PatKind::Binding(.., ident, None) = tmp.pat.kind;

            // foo() = bar();
            if let StmtKind::Semi(ref first) = w[1].kind;
            if let ExprKind::Assign(ref lhs1, ref rhs1) = first.kind;

            // bar() = t;
            if let StmtKind::Semi(ref second) = w[2].kind;
            if let ExprKind::Assign(ref lhs2, ref rhs2) = second.kind;
            if let ExprKind::Path(QPath::Resolved(None, ref rhs2)) = rhs2.kind;
            if rhs2.segments.len() == 1;

            if ident.as_str() == rhs2.segments[0].ident.as_str();
            if SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1);
            if SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2);
            then {
                if let ExprKind::Field(ref lhs1, _) = lhs1.kind {
                    if let ExprKind::Field(ref lhs2, _) = lhs2.kind {
                        if lhs1.hir_id.owner_def_id() == lhs2.hir_id.owner_def_id() {
                            return;
                        }
                    }
                }

                let slice = check_for_slice(cx, lhs1, lhs2);

                let (replace, what, sugg) = if let Slice::NotSwappable = slice {
                    return;
                } else if let Slice::Swappable(slice, idx1, idx2) = slice {
                    if let Some(slice) = Sugg::hir_opt(cx, slice) {
                        (
                            false,
                            format!(" elements of `{}`", slice),
                            format!(
                                "{}.swap({}, {})",
                                slice.maybe_par(),
                                snippet(cx, idx1.span, ".."),
                                snippet(cx, idx2.span, ".."),
                            ),
                        )
                    } else {
                        (false, String::new(), String::new())
                    }
                } else if let (Some(first), Some(second)) = (Sugg::hir_opt(cx, lhs1), Sugg::hir_opt(cx, rhs1)) {
                    (
                        true,
                        format!(" `{}` and `{}`", first, second),
                        format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr()),
                    )
                } else {
                    (true, String::new(), String::new())
                };

                let span = w[0].span.to(second.span);

                span_lint_and_then(
                    cx,
                    MANUAL_SWAP,
                    span,
                    &format!("this looks like you are swapping{} manually", what),
                    |db| {
                        if !sugg.is_empty() {
                            db.span_suggestion(
                                span,
                                "try",
                                sugg,
                                Applicability::Unspecified,
                            );

                            if replace {
                                db.note("or maybe you should use `std::mem::replace`?");
                            }
                        }
                    }
                );
            }
        }
    }
}

enum Slice<'a> {
    /// `slice.swap(idx1, idx2)` can be used
    ///
    /// ## Example
    ///
    /// ```rust
    /// let t = a[1];
    /// a[1] = a[0];
    /// a[0] = t;
    /// // can be written as
    /// a.swap(0, 1);
    /// ```
    Swappable(&'a Expr, &'a Expr, &'a Expr),
    /// The `swap` function cannot be used.
    ///
    /// ## Example
    ///
    /// ```rust
    /// let t = a[0][1];
    /// a[0][1] = a[1][0];
    /// a[1][0] = t;
    /// ```
    NotSwappable,
    /// Not a slice
    None,
}

/// Checks if both expressions are index operations into "slice-like" types.
fn check_for_slice<'a>(cx: &LateContext<'_, '_>, lhs1: &'a Expr, lhs2: &'a Expr) -> Slice<'a> {
    if let ExprKind::Index(ref lhs1, ref idx1) = lhs1.kind {
        if let ExprKind::Index(ref lhs2, ref idx2) = lhs2.kind {
            if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) {
                let ty = walk_ptrs_ty(cx.tables.expr_ty(lhs1));

                if matches!(ty.kind, ty::Slice(_))
                    || matches!(ty.kind, ty::Array(_, _))
                    || is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type"))
                    || match_type(cx, ty, &paths::VEC_DEQUE)
                {
                    return Slice::Swappable(lhs1, idx1, idx2);
                }
            } else {
                return Slice::NotSwappable;
            }
        }
    }

    Slice::None
}

/// Implementation of the `ALMOST_SWAPPED` lint.
fn check_suspicious_swap(cx: &LateContext<'_, '_>, block: &Block) {
    for w in block.stmts.windows(2) {
        if_chain! {
            if let StmtKind::Semi(ref first) = w[0].kind;
            if let StmtKind::Semi(ref second) = w[1].kind;
            if !differing_macro_contexts(first.span, second.span);
            if let ExprKind::Assign(ref lhs0, ref rhs0) = first.kind;
            if let ExprKind::Assign(ref lhs1, ref rhs1) = second.kind;
            if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs0, rhs1);
            if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, rhs0);
            then {
                let lhs0 = Sugg::hir_opt(cx, lhs0);
                let rhs0 = Sugg::hir_opt(cx, rhs0);
                let (what, lhs, rhs) = if let (Some(first), Some(second)) = (lhs0, rhs0) {
                    (
                        format!(" `{}` and `{}`", first, second),
                        first.mut_addr().to_string(),
                        second.mut_addr().to_string(),
                    )
                } else {
                    (String::new(), String::new(), String::new())
                };

                let span = first.span.to(second.span);

                span_lint_and_then(cx,
                                   ALMOST_SWAPPED,
                                   span,
                                   &format!("this looks like you are trying to swap{}", what),
                                   |db| {
                                       if !what.is_empty() {
                                           db.span_suggestion(
                                               span,
                                               "try",
                                               format!(
                                                   "std::mem::swap({}, {})",
                                                   lhs,
                                                   rhs,
                                               ),
                                               Applicability::MaybeIncorrect,
                                           );
                                           db.note("or maybe you should use `std::mem::replace`?");
                                       }
                                   });
            }
        }
    }
}
<|endoftext|>


<commit_before>use criterion::{self, criterion_group, criterion_main, Criterion};
use pretty_assertions::assert_eq;
use quick_xml::{self, events::Event, Reader};
use serde::Deserialize;
use serde_xml_rs;
use xml::reader::{EventReader, XmlEvent};

static SOURCE: &str = include_str!("../../tests/documents/sample_rss.xml");

/// Runs benchmarks for several XML libraries using low-level API
fn low_level_comparison(c: &mut Criterion) {
    let mut group = c.benchmark_group("low-level API");

    group.bench_function("quick_xml", |b| {
        b.iter(|| {
            let mut r = Reader::from_reader(SOURCE.as_bytes());
            r.check_end_names(false).check_comments(false);
            let mut count = criterion::black_box(0);
            let mut buf = Vec::new();
            loop {
                match r.read_event_into(&mut buf) {
                    Ok(Event::Start(_)) | Ok(Event::Empty(_)) => count += 1,
                    Ok(Event::Eof) => break,
                    _ => (),
                }
                buf.clear();
            }
            assert_eq!(count, 1550, "Overall tag count in ./tests/documents/sample_rss.xml");
        })
    });

    group.bench_function("maybe_xml", |b| {
        use maybe_xml::eval::recv::RecvEvaluator;
        use maybe_xml::token::borrowed::Token;

        b.iter(|| {
            let mut input = SOURCE.as_bytes();
            let mut eval = RecvEvaluator::new();

            let mut count = criterion::black_box(0);
            loop {
                let consumed = eval.recv(input);
                match eval.next_token() {
                    Ok(Some(Token::StartTag(_))) => count += 1,
                    Ok(Some(Token::EmptyElementTag(_))) => count += 1,
                    Ok(Some(Token::Eof)) => break,
                    Ok(Some(Token::EofWithBytesNotEvaluated(_))) => break,
                    _ => (),
                }
                input = &input[consumed..];
            }
            assert_eq!(count, 1550, "Overall tag count in ./tests/documents/sample_rss.xml");
        })
    });

    group.bench_function("rapid-xml", |b| {
        use rapid_xml::parser::{EventCode, Parser};

        b.iter(|| {
            let mut r = Parser::new(SOURCE.as_bytes());

            let mut count = criterion::black_box(0);
            loop {
                // Makes no progress if error is returned, so need unwrap()
                match r.next().unwrap().code() {
                    EventCode::StartTag => count += 1,
                    EventCode::Eof => break,
                    _ => (),
                }
            }
            assert_eq!(count, 1550, "Overall tag count in ./tests/documents/sample_rss.xml");
        })
    });

    group.bench_function("xmlparser", |b| {
        use xmlparser::{Token, Tokenizer};

        b.iter(|| {
            let mut count = criterion::black_box(0);
            for token in Tokenizer::from(SOURCE) {
                match token {
                    Ok(Token::ElementStart { .. }) => count += 1,
                    _ => (),
                }
            }
            assert_eq!(count, 1550, "Overall tag count in ./tests/documents/sample_rss.xml");
        })
    });

    group.bench_function("RustyXML", |b| {
        use rusty_xml::{Event, Parser};

        b.iter(|| {
            let mut r = Parser::new();
            r.feed_str(SOURCE);

            let mut count = criterion::black_box(0);
            for event in r {
                match event.unwrap() {
                    Event::ElementStart(_) => count += 1,
                    _ => (),
                }
            }
            assert_eq!(count, 1550, "Overall tag count in ./tests/documents/sample_rss.xml");
        })
    });

    group.bench_function("xml_oxide", |b| {
        use xml_oxide::sax::parser::Parser;
        use xml_oxide::sax::Event;

        b.iter(|| {
            let mut r = Parser::from_reader(SOURCE.as_bytes());

            let mut count = criterion::black_box(0);
            loop {
                // Makes no progress if error is returned, so need unwrap()
                match r.read_event().unwrap() {
                    Event::StartElement(_) => count += 1,
                    Event::EndDocument => break,
                    _ => (),
                }
            }
            assert_eq!(count, 1550, "Overall tag count in ./tests/sample_rss.xml");
        })
    });

    group.bench_function("xml5ever", |b| {
        use xml5ever::buffer_queue::BufferQueue;
        use xml5ever::tokenizer::{TagKind, Token, TokenSink, XmlTokenizer};

        struct Sink(usize);
        impl TokenSink for Sink {
            fn process_token(&mut self, token: Token) {
                match token {
                    Token::TagToken(tag) if tag.kind == TagKind::StartTag => self.0 += 1,
                    Token::TagToken(tag) if tag.kind == TagKind::EmptyTag => self.0 += 1,
                    _ => (),
                }
            }
        }

        // Copied from xml5ever benchmarks
        // https://github.com/servo/html5ever/blob/429f23943b24f739b78f4d703620d7b1b526475b/xml5ever/benches/xml5ever.rs
        b.iter(|| {
            let sink = criterion::black_box(Sink(0));
            let mut tok = XmlTokenizer::new(sink, Default::default());
            let mut buffer = BufferQueue::new();
            buffer.push_back(SOURCE.into());
            let _ = tok.feed(&mut buffer);
            tok.end();

            assert_eq!(
                tok.sink.0, 1550,
                "Overall tag count in ./tests/documents/sample_rss.xml"
            );
        })
    });

    group.bench_function("xml_rs", |b| {
        b.iter(|| {
            let r = EventReader::new(SOURCE.as_bytes());
            let mut count = criterion::black_box(0);
            for e in r {
                if let Ok(XmlEvent::StartElement { .. }) = e {
                    count += 1;
                }
            }
            assert_eq!(count, 1550, "Overall tag count in ./tests/documents/sample_rss.xml");
        })
    });
    group.finish();
}

/// Runs benchmarks for several XML libraries using serde deserialization
#[allow(dead_code)] // We do not use structs
fn serde_comparison(c: &mut Criterion) {
    let mut group = c.benchmark_group("serde");
    #[derive(Debug, Deserialize)]
    struct Rss {
        channel: Channel,
    }

    #[derive(Debug, Deserialize)]
    struct Channel {
        title: String,
        #[serde(rename = "item", default)]
        items: Vec<Item>,
    }

    #[derive(Debug, Deserialize)]
    struct Item {
        title: String,
        link: String,
        #[serde(rename = "pubDate")]
        pub_date: String,
        enclosure: Option<Enclosure>,
    }

    #[derive(Debug, Deserialize)]
    struct Enclosure {
        url: String,
        length: String,
        #[serde(rename = "type")]
        typ: String,
    }

    group.bench_function("quick_xml", |b| {
        b.iter(|| {
            let rss: Rss = quick_xml::de::from_str(SOURCE).unwrap();
            assert_eq!(rss.channel.items.len(), 99);
        })
    });

    /* NOTE: Most parts of deserializer are not implemented yet, so benchmark failed
    group.bench_function("rapid-xml", |b| {
        use rapid_xml::de::Deserializer;
        use rapid_xml::parser::Parser;

        b.iter(|| {
            let mut r = Parser::new(SOURCE.as_bytes());
            let mut de = Deserializer::new(&mut r).unwrap();
            let rss = Rss::deserialize(&mut de).unwrap();
            assert_eq!(rss.channel.items.len(), 99);
        });
    });*/

    group.bench_function("xml_rs", |b| {
        b.iter(|| {
            let rss: Rss = serde_xml_rs::from_str(SOURCE).unwrap();
            assert_eq!(rss.channel.items.len(), 99);
        });
    });
    group.finish();
}

criterion_group!(benches, low_level_comparison, serde_comparison);
criterion_main!(benches);
<commit_msg>cargo fmt for `compare` crate<commit_after>use criterion::{self, criterion_group, criterion_main, Criterion};
use pretty_assertions::assert_eq;
use quick_xml::{self, events::Event, Reader};
use serde::Deserialize;
use serde_xml_rs;
use xml::reader::{EventReader, XmlEvent};

static SOURCE: &str = include_str!("../../tests/documents/sample_rss.xml");

/// Runs benchmarks for several XML libraries using low-level API
fn low_level_comparison(c: &mut Criterion) {
    let mut group = c.benchmark_group("low-level API");

    group.bench_function("quick_xml", |b| {
        b.iter(|| {
            let mut r = Reader::from_reader(SOURCE.as_bytes());
            r.check_end_names(false).check_comments(false);
            let mut count = criterion::black_box(0);
            let mut buf = Vec::new();
            loop {
                match r.read_event_into(&mut buf) {
                    Ok(Event::Start(_)) | Ok(Event::Empty(_)) => count += 1,
                    Ok(Event::Eof) => break,
                    _ => (),
                }
                buf.clear();
            }
            assert_eq!(
                count, 1550,
                "Overall tag count in ./tests/documents/sample_rss.xml"
            );
        })
    });

    group.bench_function("maybe_xml", |b| {
        use maybe_xml::eval::recv::RecvEvaluator;
        use maybe_xml::token::borrowed::Token;

        b.iter(|| {
            let mut input = SOURCE.as_bytes();
            let mut eval = RecvEvaluator::new();

            let mut count = criterion::black_box(0);
            loop {
                let consumed = eval.recv(input);
                match eval.next_token() {
                    Ok(Some(Token::StartTag(_))) => count += 1,
                    Ok(Some(Token::EmptyElementTag(_))) => count += 1,
                    Ok(Some(Token::Eof)) => break,
                    Ok(Some(Token::EofWithBytesNotEvaluated(_))) => break,
                    _ => (),
                }
                input = &input[consumed..];
            }
            assert_eq!(
                count, 1550,
                "Overall tag count in ./tests/documents/sample_rss.xml"
            );
        })
    });

    group.bench_function("rapid-xml", |b| {
        use rapid_xml::parser::{EventCode, Parser};

        b.iter(|| {
            let mut r = Parser::new(SOURCE.as_bytes());

            let mut count = criterion::black_box(0);
            loop {
                // Makes no progress if error is returned, so need unwrap()
                match r.next().unwrap().code() {
                    EventCode::StartTag => count += 1,
                    EventCode::Eof => break,
                    _ => (),
                }
            }
            assert_eq!(
                count, 1550,
                "Overall tag count in ./tests/documents/sample_rss.xml"
            );
        })
    });

    group.bench_function("xmlparser", |b| {
        use xmlparser::{Token, Tokenizer};

        b.iter(|| {
            let mut count = criterion::black_box(0);
            for token in Tokenizer::from(SOURCE) {
                match token {
                    Ok(Token::ElementStart { .. }) => count += 1,
                    _ => (),
                }
            }
            assert_eq!(
                count, 1550,
                "Overall tag count in ./tests/documents/sample_rss.xml"
            );
        })
    });

    group.bench_function("RustyXML", |b| {
        use rusty_xml::{Event, Parser};

        b.iter(|| {
            let mut r = Parser::new();
            r.feed_str(SOURCE);

            let mut count = criterion::black_box(0);
            for event in r {
                match event.unwrap() {
                    Event::ElementStart(_) => count += 1,
                    _ => (),
                }
            }
            assert_eq!(
                count, 1550,
                "Overall tag count in ./tests/documents/sample_rss.xml"
            );
        })
    });

    group.bench_function("xml_oxide", |b| {
        use xml_oxide::sax::parser::Parser;
        use xml_oxide::sax::Event;

        b.iter(|| {
            let mut r = Parser::from_reader(SOURCE.as_bytes());

            let mut count = criterion::black_box(0);
            loop {
                // Makes no progress if error is returned, so need unwrap()
                match r.read_event().unwrap() {
                    Event::StartElement(_) => count += 1,
                    Event::EndDocument => break,
                    _ => (),
                }
            }
            assert_eq!(count, 1550, "Overall tag count in ./tests/sample_rss.xml");
        })
    });

    group.bench_function("xml5ever", |b| {
        use xml5ever::buffer_queue::BufferQueue;
        use xml5ever::tokenizer::{TagKind, Token, TokenSink, XmlTokenizer};

        struct Sink(usize);
        impl TokenSink for Sink {
            fn process_token(&mut self, token: Token) {
                match token {
                    Token::TagToken(tag) if tag.kind == TagKind::StartTag => self.0 += 1,
                    Token::TagToken(tag) if tag.kind == TagKind::EmptyTag => self.0 += 1,
                    _ => (),
                }
            }
        }

        // Copied from xml5ever benchmarks
        // https://github.com/servo/html5ever/blob/429f23943b24f739b78f4d703620d7b1b526475b/xml5ever/benches/xml5ever.rs
        b.iter(|| {
            let sink = criterion::black_box(Sink(0));
            let mut tok = XmlTokenizer::new(sink, Default::default());
            let mut buffer = BufferQueue::new();
            buffer.push_back(SOURCE.into());
            let _ = tok.feed(&mut buffer);
            tok.end();

            assert_eq!(
                tok.sink.0, 1550,
                "Overall tag count in ./tests/documents/sample_rss.xml"
            );
        })
    });

    group.bench_function("xml_rs", |b| {
        b.iter(|| {
            let r = EventReader::new(SOURCE.as_bytes());
            let mut count = criterion::black_box(0);
            for e in r {
                if let Ok(XmlEvent::StartElement { .. }) = e {
                    count += 1;
                }
            }
            assert_eq!(
                count, 1550,
                "Overall tag count in ./tests/documents/sample_rss.xml"
            );
        })
    });
    group.finish();
}

/// Runs benchmarks for several XML libraries using serde deserialization
#[allow(dead_code)] // We do not use structs
fn serde_comparison(c: &mut Criterion) {
    let mut group = c.benchmark_group("serde");
    #[derive(Debug, Deserialize)]
    struct Rss {
        channel: Channel,
    }

    #[derive(Debug, Deserialize)]
    struct Channel {
        title: String,
        #[serde(rename = "item", default)]
        items: Vec<Item>,
    }

    #[derive(Debug, Deserialize)]
    struct Item {
        title: String,
        link: String,
        #[serde(rename = "pubDate")]
        pub_date: String,
        enclosure: Option<Enclosure>,
    }

    #[derive(Debug, Deserialize)]
    struct Enclosure {
        url: String,
        length: String,
        #[serde(rename = "type")]
        typ: String,
    }

    group.bench_function("quick_xml", |b| {
        b.iter(|| {
            let rss: Rss = quick_xml::de::from_str(SOURCE).unwrap();
            assert_eq!(rss.channel.items.len(), 99);
        })
    });

    /* NOTE: Most parts of deserializer are not implemented yet, so benchmark failed
    group.bench_function("rapid-xml", |b| {
        use rapid_xml::de::Deserializer;
        use rapid_xml::parser::Parser;

        b.iter(|| {
            let mut r = Parser::new(SOURCE.as_bytes());
            let mut de = Deserializer::new(&mut r).unwrap();
            let rss = Rss::deserialize(&mut de).unwrap();
            assert_eq!(rss.channel.items.len(), 99);
        });
    });*/

    group.bench_function("xml_rs", |b| {
        b.iter(|| {
            let rss: Rss = serde_xml_rs::from_str(SOURCE).unwrap();
            assert_eq!(rss.channel.items.len(), 99);
        });
    });
    group.finish();
}

criterion_group!(benches, low_level_comparison, serde_comparison);
criterion_main!(benches);
<|endoftext|>