<commit_before>use std::env;
use std::fs;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::path::Path;
use std::process;

fn main() {
    static ENV_VAR: &str = "PLATFORM";
    static FILE_NAME: &str = "platform";
    static APP_HEAP_SIZE: &str = "APP_HEAP_SIZE";
    static KERNEL_HEAP_SIZE: &str = "KERNEL_HEAP_SIZE";

    println!("cargo:rerun-if-env-changed={}", ENV_VAR);
    println!("cargo:rerun-if-env-changed={}", APP_HEAP_SIZE);
    println!("cargo:rerun-if-env-changed={}", KERNEL_HEAP_SIZE);
    println!("cargo:rerun-if-changed={}", FILE_NAME);

    let platform_name = read_env_var(ENV_VAR).or_else(|| read_board_name_from_file(FILE_NAME));
    if let Some(platform_name) = platform_name {
        println!("cargo:rustc-env={}={}", ENV_VAR, platform_name);
        copy_linker_file(&platform_name.trim());
    } else {
        println!(
            "cargo:warning=No platform specified. \
             Remember to manually specify a linker file.",
        );
    }

    set_default_env(APP_HEAP_SIZE, "1024");
    set_default_env(KERNEL_HEAP_SIZE, "1024");
}

fn set_default_env(env_var: &str, default: &str) {
    if let Some(s) = read_env_var(env_var) {
        println!("cargo:rustc-env={}={}", env_var, s);
    } else {
        // Just use a default of 1024 if nothing is passed in
        println!("cargo:rustc-env={}={}", env_var, default);
    }
}

fn read_env_var(env_var: &str) -> Option<String> {
    env::var_os(env_var).map(|os_string| os_string.into_string().unwrap())
}

fn read_board_name_from_file(file_name: &str) -> Option<String> {
    let path = Path::new(file_name);
    if !path.exists() {
        return None;
    }

    let board_file = File::open(path).unwrap();
    let mut board_name = String::new();
    BufReader::new(board_file)
        .read_line(&mut board_name)
        .unwrap();
    Some(board_name)
}

fn copy_linker_file(platform_name: &str) {
    let linker_file_name = format!("boards/layout_{}.ld", platform_name);
    let path = Path::new(&linker_file_name);
    if !path.exists() {
        println!("Cannot find layout file {:?}", path);
        process::exit(1);
    }
    fs::copy(linker_file_name, "layout.ld").unwrap();
}
<commit_msg>Improve change detection in build.rs<commit_after>use std::env;
use std::fs;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::path::Path;
use std::process;

static LAYOUT_FILE_NAME: &str = "layout.ld";

fn main() {
    static PLATFORM_ENV_VAR: &str = "PLATFORM";
    static PLATFORM_FILE_NAME: &str = "platform";
    static APP_HEAP_SIZE: &str = "APP_HEAP_SIZE";
    static KERNEL_HEAP_SIZE: &str = "KERNEL_HEAP_SIZE";

    println!("cargo:rerun-if-env-changed={}", PLATFORM_ENV_VAR);
    println!("cargo:rerun-if-env-changed={}", APP_HEAP_SIZE);
    println!("cargo:rerun-if-env-changed={}", KERNEL_HEAP_SIZE);
    println!("cargo:rerun-if-changed={}", PLATFORM_FILE_NAME);
    println!("cargo:rerun-if-changed={}", LAYOUT_FILE_NAME);

    let platform_name =
        read_env_var(PLATFORM_ENV_VAR).or_else(|| read_board_name_from_file(PLATFORM_FILE_NAME));
    if let Some(platform_name) = platform_name {
        println!("cargo:rustc-env={}={}", PLATFORM_ENV_VAR, platform_name);
        copy_linker_file(platform_name.trim());
    } else {
        println!(
            "cargo:warning=No platform specified. \
             Remember to manually specify a linker file.",
        );
    }

    set_default_env(APP_HEAP_SIZE, "1024");
    set_default_env(KERNEL_HEAP_SIZE, "1024");
}

fn set_default_env(env_var: &str, default: &str) {
    if let Some(s) = read_env_var(env_var) {
        println!("cargo:rustc-env={}={}", env_var, s);
    } else {
        // Just use a default of 1024 if nothing is passed in
        println!("cargo:rustc-env={}={}", env_var, default);
    }
}

fn read_env_var(env_var: &str) -> Option<String> {
    env::var_os(env_var).map(|os_string| os_string.into_string().unwrap())
}

fn read_board_name_from_file(file_name: &str) -> Option<String> {
    let path = Path::new(file_name);
    if !path.exists() {
        return None;
    }

    let board_file = File::open(path).unwrap();
    let mut board_name = String::new();
    BufReader::new(board_file)
        .read_line(&mut board_name)
        .unwrap();
    Some(board_name)
}

fn copy_linker_file(platform_name: &str) {
    let linker_file_name = format!("boards/layout_{}.ld", platform_name);
    let path = Path::new(&linker_file_name);
    if !path.exists() {
        println!("Cannot find layout file {:?}", path);
        process::exit(1);
    }
    fs::copy(linker_file_name, LAYOUT_FILE_NAME).unwrap();
}
<|endoftext|>


<commit_before>fn main() {
    if std::env::var("CARGO_FEATURE_STATIC").is_ok() {
        let static_path = std::env::var("ODBC_SYS_STATIC_PATH").unwrap_or("/usr/lib".to_string());
        println!("cargo:rerun-if-env-changed=ODBC_SYS_STATIC_PATH");
        println!("cargo:rustc-link-search=native={}", static_path);
        println!("cargo:rustc-link-lib=static=odbc");
    }

    if cfg!(target_os = "macos") {
        // if we're on Mac OS X we'll kindly add DYLD_LIBRARY_PATH to rustc's
        // linker search path
        if let Some(dyld_paths) = option_env!("DYLD_LIBRARY_PATH") {
            print_paths(dyld_paths);
        }
        // if we're on Mac OS X we'll kindly add DYLD_FALLBACK_LIBRARY_PATH to rustc's
        // linker search path
        if let Some(dyld_fallback_paths) = option_env!("DYLD_FALLBACK_LIBRARY_PATH") {
            print_paths(dyld_fallback_paths);
        }
    }
}

fn print_paths(paths: &str) {
    for path in paths.split(':').filter(|x| !x.is_empty()) {
        println!("cargo:rustc-link-search=native={}", path)
    }
}
<commit_msg>Add ltdl linking<commit_after>fn main() {
    if std::env::var("CARGO_FEATURE_STATIC").is_ok() {
        let static_path = std::env::var("ODBC_SYS_STATIC_PATH").unwrap_or("/usr/lib".to_string());
        println!("cargo:rerun-if-env-changed=ODBC_SYS_STATIC_PATH");
        println!("cargo:rustc-link-search=native={}", static_path);
        println!("cargo:rustc-link-lib=static=odbc");
        if cfg!(not(target_os = "windows")) {
            println!("cargo:rustc-link-lib=static=ltdl");
        }
    }

    if cfg!(target_os = "macos") {
        // if we're on Mac OS X we'll kindly add DYLD_LIBRARY_PATH to rustc's
        // linker search path
        if let Some(dyld_paths) = option_env!("DYLD_LIBRARY_PATH") {
            print_paths(dyld_paths);
        }
        // if we're on Mac OS X we'll kindly add DYLD_FALLBACK_LIBRARY_PATH to rustc's
        // linker search path
        if let Some(dyld_fallback_paths) = option_env!("DYLD_FALLBACK_LIBRARY_PATH") {
            print_paths(dyld_fallback_paths);
        }
    }
}

fn print_paths(paths: &str) {
    for path in paths.split(':').filter(|x| !x.is_empty()) {
        println!("cargo:rustc-link-search=native={}", path)
    }
}
<|endoftext|>


<commit_before>extern crate pkg_config;
extern crate gcc;

use std::fs::{self,File};
use std::path::Path;

use std::io::prelude::*;

fn main() {
    let libraw = pkg_config::find_library("libraw_r").unwrap();

    // libraw_iparams_t members

    if check_member(&libraw, "libraw_iparams_t", "software") {
        println!("cargo:rustc-cfg=have_iparams_software");
    }

    if check_member(&libraw, "libraw_iparams_t", "xtrans") {
        println!("cargo:rustc-cfg=have_iparams_xtrans");
    }

    if check_member(&libraw, "libraw_iparams_t", "xtrans_abs") {
        println!("cargo:rustc-cfg=have_iparams_xtrans_abs");
    }

    if check_member(&libraw, "libraw_iparams_t", "xmplen") {
        println!("cargo:rustc-cfg=have_iparams_xmplen");
    }

    if check_member(&libraw, "libraw_iparams_t", "xmpdata") {
        println!("cargo:rustc-cfg=have_iparams_xmpdata");
    }

    // libraw_output_params_t members

    if check_member(&libraw, "libraw_output_params_t", "sony_arw2_hack") {
        println!("cargo:rustc-cfg=have_output_params_sony_arw2_hack");
    }

    if check_member(&libraw, "libraw_output_params_t", "afd_noise_att") {
        println!("cargo:rustc-cfg=have_output_params_afd_noise_att");
    }

    if check_member(&libraw, "libraw_output_params_t", "afd_noise_thres") {
        println!("cargo:rustc-cfg=have_output_params_afd_noise_thres");
    }

    if check_member(&libraw, "libraw_output_params_t", "afd_luminance_passes") {
        println!("cargo:rustc-cfg=have_output_params_afd_luminance_passes");
    }

    if check_member(&libraw, "libraw_output_params_t", "afd_chrominance_method") {
        println!("cargo:rustc-cfg=have_output_params_afd_chrominance_method");
    }

    if check_member(&libraw, "libraw_output_params_t", "afd_luminance_only") {
        println!("cargo:rustc-cfg=have_output_params_afd_luminance_only");
    }

    if check_member(&libraw, "libraw_output_params_t", "no_auto_scale") {
        println!("cargo:rustc-cfg=have_output_params_no_auto_scale");
    }

    if check_member(&libraw, "libraw_output_params_t", "no_interpolation") {
        println!("cargo:rustc-cfg=have_output_params_no_interpolation");
    }

    if check_member(&libraw, "libraw_output_params_t", "sraw_ycc") {
        println!("cargo:rustc-cfg=have_output_params_sraw_ycc");
    }

    if check_member(&libraw, "libraw_output_params_t", "force_foveon_x3f") {
        println!("cargo:rustc-cfg=have_output_params_force_foveon_x3f");
    }

    if check_member(&libraw, "libraw_output_params_t", "x3f_flags") {
        println!("cargo:rustc-cfg=have_output_params_x3f_flags");
    }

    if check_member(&libraw, "libraw_output_params_t", "sony_arw2_options") {
        println!("cargo:rustc-cfg=have_output_params_sony_arw2_options");
    }

    if check_member(&libraw, "libraw_output_params_t", "sony_arw2_posterization_thr") {
        println!("cargo:rustc-cfg=have_output_params_sony_arw2_posterization_thr");
    }

    if check_member(&libraw, "libraw_output_params_t", "coolscan_nef_gamma") {
        println!("cargo:rustc-cfg=have_output_params_coolscan_nef_gamma");
    }

    // libraw_colordata_t members

    if check_member(&libraw, "libraw_colordata_t", "black_stat") {
        println!("cargo:rustc-cfg=have_colordata_black_stat");
    }

    if check_member(&libraw, "libraw_colordata_t", "baseline_exposure") {
        println!("cargo:rustc-cfg=have_colordata_baseline_exposure");
    }

    if check_member(&libraw, "libraw_colordata_t", "OlympusSensorCalibration") {
        println!("cargo:rustc-cfg=have_colordata_olympus_sensor_calibration");
    }

    if check_member(&libraw, "libraw_colordata_t", "FujiExpoMidPointShift") {
        println!("cargo:rustc-cfg=have_colordata_fuji_expo_mid_point_shift");
    }

    if check_member(&libraw, "libraw_colordata_t", "digitalBack_color") {
        println!("cargo:rustc-cfg=have_colordata_digital_back_color");
    }

    // libraw_rawdata_t members

    if check_member(&libraw, "libraw_rawdata_t", "ph1_rblack") {
        println!("cargo:rustc-cfg=have_rawdata_ph1_rblack");
    }

    // ph1_t layout

    if check_member(&libraw, "struct ph1_t", "black_off") {
        println!("cargo:rustc-cfg=have_ph1_black_off");
    }

    // structs

    let mut defines = Vec::<&str>::with_capacity(16);

    if check_type(&libraw, "libraw_lensinfo_t") {
        println!("cargo:rustc-cfg=have_lensinfo");
        defines.push("HAVE_LENSINFO");
    }

    if check_type(&libraw, "libraw_nikonlens_t") {
        println!("cargo:rustc-cfg=have_nikonlens");
        defines.push("HAVE_NIKONLENS");
    }

    if check_type(&libraw, "libraw_dnglens_t") {
        println!("cargo:rustc-cfg=have_dnglens");
        defines.push("HAVE_DNGLENS");
    }

    if check_type(&libraw, "libraw_makernotes_lens_t") {
        println!("cargo:rustc-cfg=have_makernotes_lens");
        defines.push("HAVE_MAKERNOTES_LENS");
    }

    if check_type(&libraw, "libraw_ph1_t") {
        println!("cargo:rustc-cfg=have_ph1");
        defines.push("HAVE_PH1");
    }

    if check_type(&libraw, "libraw_dng_color_t") {
        println!("cargo:rustc-cfg=have_dng_color");
        defines.push("HAVE_DNG_COLOR");
    }

    if check_type(&libraw, "libraw_canon_makernotes_t") {
        println!("cargo:rustc-cfg=have_canon_makernotes");
        defines.push("HAVE_CANON_MAKERNOTES");
    }

    if check_type(&libraw, "libraw_gps_info_t") {
        println!("cargo:rustc-cfg=have_gps_info");
        defines.push("HAVE_GPS_INFO");
    }

    // compile test helper functions
    let mut gcc = gcc::Config::new();

    for path in libraw.include_paths {
        gcc.include(path.to_str().unwrap());
    }

    for define in defines {
        gcc.define(define, None);
    }

    gcc.file("tests/sizes.c").compile("libsizes.a");
}

fn check_type(library: &pkg_config::Library, type_name: &str) -> bool {
    let test_file_path = format!("target/build/check_{}.c", type_name);
    let test_file_name = Path::new(&test_file_path);

    fs::create_dir_all("target/build").unwrap();

    {
        let mut test_file = File::create(test_file_name).unwrap();

        writeln!(&mut test_file, "#include <libraw.h>").unwrap();
        writeln!(&mut test_file, "int main() {{").unwrap();
        writeln!(&mut test_file, "  if (sizeof({})) {{", type_name).unwrap();
        writeln!(&mut test_file, "    return 0;").unwrap();
        writeln!(&mut test_file, "  }}").unwrap();
        writeln!(&mut test_file, "  return 0;").unwrap();
        writeln!(&mut test_file, "}}").unwrap();
    }

    let mut gcc = gcc::Config::new();

    for path in &library.include_paths {
        gcc.include(path);
    }

    let mut command = gcc.get_compiler().to_command();

    let output = command.arg("-c").arg(test_file_name).
        arg("-o").arg("target/build/conftest.o").
        output().unwrap();

    output.status.success()
}

fn check_member(library: &pkg_config::Library, type_name: &str, member_name: &str) -> bool {
    let test_file_path = format!("target/build/check_{}_{}.c", type_name, member_name);
    let test_file_name = Path::new(&test_file_path);

    fs::create_dir_all("target/build").unwrap();

    {
        let mut test_file = File::create(test_file_name).unwrap();

        writeln!(&mut test_file, "#include <libraw.h>").unwrap();
        writeln!(&mut test_file, "int main() {{").unwrap();
        writeln!(&mut test_file, "  static {} aggr;", type_name).unwrap();
        writeln!(&mut test_file, "  if (aggr.{}) {{", member_name).unwrap();
        writeln!(&mut test_file, "    return 0;").unwrap();
        writeln!(&mut test_file, "  }}").unwrap();
        writeln!(&mut test_file, "  return 0;").unwrap();
        writeln!(&mut test_file, "}}").unwrap();
    }

    let mut gcc = gcc::Config::new();

    for path in &library.include_paths {
        gcc.include(path);
    }

    let mut command = gcc.get_compiler().to_command();

    let output = command.arg("-c").arg(test_file_name).
        arg("-o").arg("target/build/conftest.o").
        output().unwrap();

    output.status.success()
}
<commit_msg>adds minimum version<commit_after>extern crate pkg_config;
extern crate gcc;

use std::fs::{self,File};
use std::path::Path;

use std::io::prelude::*;

fn main() {
    let libraw = pkg_config::Config::new().atleast_version("0.15.0").find("libraw_r").unwrap();

    // libraw_iparams_t members

    if check_member(&libraw, "libraw_iparams_t", "software") {
        println!("cargo:rustc-cfg=have_iparams_software");
    }

    if check_member(&libraw, "libraw_iparams_t", "xtrans") {
        println!("cargo:rustc-cfg=have_iparams_xtrans");
    }

    if check_member(&libraw, "libraw_iparams_t", "xtrans_abs") {
        println!("cargo:rustc-cfg=have_iparams_xtrans_abs");
    }

    if check_member(&libraw, "libraw_iparams_t", "xmplen") {
        println!("cargo:rustc-cfg=have_iparams_xmplen");
    }

    if check_member(&libraw, "libraw_iparams_t", "xmpdata") {
        println!("cargo:rustc-cfg=have_iparams_xmpdata");
    }

    // libraw_output_params_t members

    if check_member(&libraw, "libraw_output_params_t", "sony_arw2_hack") {
        println!("cargo:rustc-cfg=have_output_params_sony_arw2_hack");
    }

    if check_member(&libraw, "libraw_output_params_t", "afd_noise_att") {
        println!("cargo:rustc-cfg=have_output_params_afd_noise_att");
    }

    if check_member(&libraw, "libraw_output_params_t", "afd_noise_thres") {
        println!("cargo:rustc-cfg=have_output_params_afd_noise_thres");
    }

    if check_member(&libraw, "libraw_output_params_t", "afd_luminance_passes") {
        println!("cargo:rustc-cfg=have_output_params_afd_luminance_passes");
    }

    if check_member(&libraw, "libraw_output_params_t", "afd_chrominance_method") {
        println!("cargo:rustc-cfg=have_output_params_afd_chrominance_method");
    }

    if check_member(&libraw, "libraw_output_params_t", "afd_luminance_only") {
        println!("cargo:rustc-cfg=have_output_params_afd_luminance_only");
    }

    if check_member(&libraw, "libraw_output_params_t", "no_auto_scale") {
        println!("cargo:rustc-cfg=have_output_params_no_auto_scale");
    }

    if check_member(&libraw, "libraw_output_params_t", "no_interpolation") {
        println!("cargo:rustc-cfg=have_output_params_no_interpolation");
    }

    if check_member(&libraw, "libraw_output_params_t", "sraw_ycc") {
        println!("cargo:rustc-cfg=have_output_params_sraw_ycc");
    }

    if check_member(&libraw, "libraw_output_params_t", "force_foveon_x3f") {
        println!("cargo:rustc-cfg=have_output_params_force_foveon_x3f");
    }

    if check_member(&libraw, "libraw_output_params_t", "x3f_flags") {
        println!("cargo:rustc-cfg=have_output_params_x3f_flags");
    }

    if check_member(&libraw, "libraw_output_params_t", "sony_arw2_options") {
        println!("cargo:rustc-cfg=have_output_params_sony_arw2_options");
    }

    if check_member(&libraw, "libraw_output_params_t", "sony_arw2_posterization_thr") {
        println!("cargo:rustc-cfg=have_output_params_sony_arw2_posterization_thr");
    }

    if check_member(&libraw, "libraw_output_params_t", "coolscan_nef_gamma") {
        println!("cargo:rustc-cfg=have_output_params_coolscan_nef_gamma");
    }

    // libraw_colordata_t members

    if check_member(&libraw, "libraw_colordata_t", "black_stat") {
        println!("cargo:rustc-cfg=have_colordata_black_stat");
    }

    if check_member(&libraw, "libraw_colordata_t", "baseline_exposure") {
        println!("cargo:rustc-cfg=have_colordata_baseline_exposure");
    }

    if check_member(&libraw, "libraw_colordata_t", "OlympusSensorCalibration") {
        println!("cargo:rustc-cfg=have_colordata_olympus_sensor_calibration");
    }

    if check_member(&libraw, "libraw_colordata_t", "FujiExpoMidPointShift") {
        println!("cargo:rustc-cfg=have_colordata_fuji_expo_mid_point_shift");
    }

    if check_member(&libraw, "libraw_colordata_t", "digitalBack_color") {
        println!("cargo:rustc-cfg=have_colordata_digital_back_color");
    }

    // libraw_rawdata_t members

    if check_member(&libraw, "libraw_rawdata_t", "ph1_rblack") {
        println!("cargo:rustc-cfg=have_rawdata_ph1_rblack");
    }

    // ph1_t layout

    if check_member(&libraw, "struct ph1_t", "black_off") {
        println!("cargo:rustc-cfg=have_ph1_black_off");
    }

    // structs

    let mut defines = Vec::<&str>::with_capacity(16);

    if check_type(&libraw, "libraw_lensinfo_t") {
        println!("cargo:rustc-cfg=have_lensinfo");
        defines.push("HAVE_LENSINFO");
    }

    if check_type(&libraw, "libraw_nikonlens_t") {
        println!("cargo:rustc-cfg=have_nikonlens");
        defines.push("HAVE_NIKONLENS");
    }

    if check_type(&libraw, "libraw_dnglens_t") {
        println!("cargo:rustc-cfg=have_dnglens");
        defines.push("HAVE_DNGLENS");
    }

    if check_type(&libraw, "libraw_makernotes_lens_t") {
        println!("cargo:rustc-cfg=have_makernotes_lens");
        defines.push("HAVE_MAKERNOTES_LENS");
    }

    if check_type(&libraw, "libraw_ph1_t") {
        println!("cargo:rustc-cfg=have_ph1");
        defines.push("HAVE_PH1");
    }

    if check_type(&libraw, "libraw_dng_color_t") {
        println!("cargo:rustc-cfg=have_dng_color");
        defines.push("HAVE_DNG_COLOR");
    }

    if check_type(&libraw, "libraw_canon_makernotes_t") {
        println!("cargo:rustc-cfg=have_canon_makernotes");
        defines.push("HAVE_CANON_MAKERNOTES");
    }

    if check_type(&libraw, "libraw_gps_info_t") {
        println!("cargo:rustc-cfg=have_gps_info");
        defines.push("HAVE_GPS_INFO");
    }

    // compile test helper functions
    let mut gcc = gcc::Config::new();

    for path in libraw.include_paths {
        gcc.include(path.to_str().unwrap());
    }

    for define in defines {
        gcc.define(define, None);
    }

    gcc.file("tests/sizes.c").compile("libsizes.a");
}

fn check_type(library: &pkg_config::Library, type_name: &str) -> bool {
    let test_file_path = format!("target/build/check_{}.c", type_name);
    let test_file_name = Path::new(&test_file_path);

    fs::create_dir_all("target/build").unwrap();

    {
        let mut test_file = File::create(test_file_name).unwrap();

        writeln!(&mut test_file, "#include <libraw.h>").unwrap();
        writeln!(&mut test_file, "int main() {{").unwrap();
        writeln!(&mut test_file, "  if (sizeof({})) {{", type_name).unwrap();
        writeln!(&mut test_file, "    return 0;").unwrap();
        writeln!(&mut test_file, "  }}").unwrap();
        writeln!(&mut test_file, "  return 0;").unwrap();
        writeln!(&mut test_file, "}}").unwrap();
    }

    let mut gcc = gcc::Config::new();

    for path in &library.include_paths {
        gcc.include(path);
    }

    let mut command = gcc.get_compiler().to_command();

    let output = command.arg("-c").arg(test_file_name).
        arg("-o").arg("target/build/conftest.o").
        output().unwrap();

    output.status.success()
}

fn check_member(library: &pkg_config::Library, type_name: &str, member_name: &str) -> bool {
    let test_file_path = format!("target/build/check_{}_{}.c", type_name, member_name);
    let test_file_name = Path::new(&test_file_path);

    fs::create_dir_all("target/build").unwrap();

    {
        let mut test_file = File::create(test_file_name).unwrap();

        writeln!(&mut test_file, "#include <libraw.h>").unwrap();
        writeln!(&mut test_file, "int main() {{").unwrap();
        writeln!(&mut test_file, "  static {} aggr;", type_name).unwrap();
        writeln!(&mut test_file, "  if (aggr.{}) {{", member_name).unwrap();
        writeln!(&mut test_file, "    return 0;").unwrap();
        writeln!(&mut test_file, "  }}").unwrap();
        writeln!(&mut test_file, "  return 0;").unwrap();
        writeln!(&mut test_file, "}}").unwrap();
    }

    let mut gcc = gcc::Config::new();

    for path in &library.include_paths {
        gcc.include(path);
    }

    let mut command = gcc.get_compiler().to_command();

    let output = command.arg("-c").arg(test_file_name).
        arg("-o").arg("target/build/conftest.o").
        output().unwrap();

    output.status.success()
}
<|endoftext|>


<commit_before>// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by the Rust Project Developers
// contributed by TeXitoi
// contributed by BurntSushi

// This technically solves the problem posed in the `regex-dna` benchmark, but
// it cheats by combining all of the replacements into a single regex and
// replacing them with a single linear scan. i.e., it re-implements
// `replace_all`. As a result, this is around 25% faster. ---AG

extern crate regex;

use std::io::{self, Read};
use std::sync::Arc;
use std::thread;

macro_rules! regex { ($re:expr) => { ::regex::Regex::new($re).unwrap() } }

fn main() {
    let mut seq = String::with_capacity(50 * (1 << 20));
    io::stdin().read_to_string(&mut seq).unwrap();
    let ilen = seq.len();

    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "");
    let clen = seq.len();
    let seq_arc = Arc::new(seq.clone());

    let variants = vec![
        regex!("agggtaaa|tttaccct"),
        regex!("[cgt]gggtaaa|tttaccc[acg]"),
        regex!("a[act]ggtaaa|tttacc[agt]t"),
        regex!("ag[act]gtaaa|tttac[agt]ct"),
        regex!("agg[act]taaa|ttta[agt]cct"),
        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
        regex!("agggt[cgt]aa|tt[acg]accct"),
        regex!("agggta[cgt]a|t[acg]taccct"),
        regex!("agggtaa[cgt]|[acg]ttaccct"),
    ];
    let mut count_promises = vec![];
    for i in 0..3 {
        let seq = seq_arc.clone();
        let res = variants[i * 3..i * 3 + 3].to_vec();
        count_promises.push(thread::spawn(move || {
            res.into_iter()
               .map(|re| (re.to_string(), re.find_iter(&seq).count()))
               .collect::<Vec<_>>()
        }));
    }

    let substs = vec![
        (b'B', "(c|g|t)"),
        (b'D', "(a|g|t)"),
        (b'H', "(a|c|t)"),
        (b'K', "(g|t)"),
        (b'M', "(a|c)"),
        (b'N', "(a|c|g|t)"),
        (b'R', "(a|g)"),
        (b'S', "(c|g)"),
        (b'V', "(a|c|g)"),
        (b'W', "(a|t)"),
        (b'Y', "(c|t)"),
    ]; // combined into one regex in `replace_all`
    let seq = replace_all(&seq, substs);

    for promise in count_promises {
        for (re, count) in promise.join().unwrap() {
            println!("{} {}", re, count);
        }
    }
    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
}

fn replace_all(text: &str, substs: Vec<(u8, &str)>) -> String {
    let mut replacements = vec![""; 256];
    let mut alternates = vec![];
    for (re, replacement) in substs {
        replacements[re as usize] = replacement;
        alternates.push((re as char).to_string());
    }

    let re = regex!(&alternates.connect("|"));
    let mut new = String::with_capacity(text.len());
    let mut last_match = 0;
    for (s, e) in re.find_iter(text) {
        new.push_str(&text[last_match..s]);
        new.push_str(replacements[text.as_bytes()[s] as usize]);
        last_match = e;
    }
    new.push_str(&text[last_match..]);
    new
}
<commit_msg>Allow deprecated connect.<commit_after>// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by the Rust Project Developers
// contributed by TeXitoi
// contributed by BurntSushi

// This technically solves the problem posed in the `regex-dna` benchmark, but
// it cheats by combining all of the replacements into a single regex and
// replacing them with a single linear scan. i.e., it re-implements
// `replace_all`. As a result, this is around 25% faster. ---AG

extern crate regex;

use std::io::{self, Read};
use std::sync::Arc;
use std::thread;

macro_rules! regex { ($re:expr) => { ::regex::Regex::new($re).unwrap() } }

fn main() {
    let mut seq = String::with_capacity(50 * (1 << 20));
    io::stdin().read_to_string(&mut seq).unwrap();
    let ilen = seq.len();

    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "");
    let clen = seq.len();
    let seq_arc = Arc::new(seq.clone());

    let variants = vec![
        regex!("agggtaaa|tttaccct"),
        regex!("[cgt]gggtaaa|tttaccc[acg]"),
        regex!("a[act]ggtaaa|tttacc[agt]t"),
        regex!("ag[act]gtaaa|tttac[agt]ct"),
        regex!("agg[act]taaa|ttta[agt]cct"),
        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
        regex!("agggt[cgt]aa|tt[acg]accct"),
        regex!("agggta[cgt]a|t[acg]taccct"),
        regex!("agggtaa[cgt]|[acg]ttaccct"),
    ];
    let mut count_promises = vec![];
    for i in 0..3 {
        let seq = seq_arc.clone();
        let res = variants[i * 3..i * 3 + 3].to_vec();
        count_promises.push(thread::spawn(move || {
            res.into_iter()
               .map(|re| (re.to_string(), re.find_iter(&seq).count()))
               .collect::<Vec<_>>()
        }));
    }

    let substs = vec![
        (b'B', "(c|g|t)"),
        (b'D', "(a|g|t)"),
        (b'H', "(a|c|t)"),
        (b'K', "(g|t)"),
        (b'M', "(a|c)"),
        (b'N', "(a|c|g|t)"),
        (b'R', "(a|g)"),
        (b'S', "(c|g)"),
        (b'V', "(a|c|g)"),
        (b'W', "(a|t)"),
        (b'Y', "(c|t)"),
    ]; // combined into one regex in `replace_all`
    let seq = replace_all(&seq, substs);

    for promise in count_promises {
        for (re, count) in promise.join().unwrap() {
            println!("{} {}", re, count);
        }
    }
    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
}

#[allow(deprecated)] // for connect -> join in Rust 1.3
fn replace_all(text: &str, substs: Vec<(u8, &str)>) -> String {
    let mut replacements = vec![""; 256];
    let mut alternates = vec![];
    for (re, replacement) in substs {
        replacements[re as usize] = replacement;
        alternates.push((re as char).to_string());
    }

    let re = regex!(&alternates.connect("|"));
    let mut new = String::with_capacity(text.len());
    let mut last_match = 0;
    for (s, e) in re.find_iter(text) {
        new.push_str(&text[last_match..s]);
        new.push_str(replacements[text.as_bytes()[s] as usize]);
        last_match = e;
    }
    new.push_str(&text[last_match..]);
    new
}
<|endoftext|>


<commit_before>//! Methods for converting shapes into triangles.

use std;
use {
    Image,
    Line,
    Matrix2d,
    Rectangle,
};
use interpolation::{lerp};

#[inline(always)]
fn tx(m: &Matrix2d, x: f64, y: f64) -> f32 {
    (m[0] * x + m[1] * y + m[2]) as f32
}

#[inline(always)]
fn ty(m: &Matrix2d, x: f64, y: f64) -> f32 {
    (m[3] * x + m[4] * y + m[5]) as f32
}

/// Streams tweened polygons using linear interpolation.
#[inline(always)]
pub fn with_lerp_polygons_tri_list_xy_f32_rgba_f32(
    m: &Matrix2d,
    polygons: &[&[f64]],
    tween_factor: f64,
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    let poly_len = polygons.len() as f64;
    // Map to interval between 0 and 1.
    let tw = tween_factor % 1.0;
    // Map negative values to positive.
    let tw = if tw < 0.0 { tw + 1.0 } else { tw };
    // Map to frame.
    let tw = tw * poly_len;
    // Get the current frame.
    let frame = tw as uint;
    // Get the next frame.
    let next_frame = (frame + 1) % polygons.len();
    let p0 = polygons[frame];
    let p1 = polygons[next_frame];
    // Get factor between frames.
    let tw = tw - frame as f64;
    let n = polygons[0].len();
    let mut i = 0u;
    stream_polygon_tri_list_xy_f32_rgba_f32(m, || {
        if i >= n { return None; }

        let j = i;
        i += 2;
        let (x0, y0) = (p0[j], p0[j+1]);
        let (x1, y1) = (p1[j], p1[j+1]);
        Some([lerp(&x0, &x1, &tw), lerp(&y0, &y1, &tw)])
    }, color, f);
}

/// Streams an ellipse specified by a resolution.
#[inline(always)]
pub fn with_ellipse_tri_list_xy_f32_rgba_f32(
    resolution: uint,
    m: &Matrix2d,
    rect: &Rectangle,
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    let (x, y, w, h) = (rect[0], rect[1], rect[2], rect[3]);
    let (cw, ch) = (0.5 * w, 0.5 * h);
    let (cx, cy) = (x + cw, y + ch);
    let n = resolution;
    let mut i = 0u;
    stream_polygon_tri_list_xy_f32_rgba_f32(m, || {
        if i >= n { return None; }

        let angle = i as f64 / n as f64 * std::f64::consts::PI_2;
        i += 1;
        Some([cx + angle.cos() * cw, cy + angle.sin() * ch])
    }, color, f);
}

/// Streams a round border line.
#[inline(always)]
pub fn with_round_border_line_tri_list_xy_f32_rgba_f32(
    _resolution_corner: uint,
    _m: &Matrix2d,
    _line: &Line,
    _round_border_radius: &f64,
    _color: [f32, ..4],
    _f: |vertices: &[f32], colors: &[f32]|) {

    /*
    let (x, y, w, h) = (rect[0], rect[1], rect[2], rect[3]);
    let radius = round_border[0];
    let n = resolution_corner * 4 + 4;
    let mut i = 0u;
    stream_polygon_tri_list_xy_f32_rgba_f32(m, || {
        if i >= n { return None; }

        let j = i;
        i += 1;
        match j {
            j if j >= resolution_corner * 3 => {
                let angle = j as f64 / (n - 3) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + w - radius, y + radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
            j if j >= resolution_corner * 2 => {
                let angle = j as f64 / (n - 2) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + radius, y + radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
            j if j >= resolution_corner * 1 => {
                let angle = j as f64 / (n - 1) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + radius, y + h - radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
            j => {
                let angle = j as f64 / (n - 0) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + w - radius, y + h - radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
        }
    }, color, f);
    */
}

/// Streams a round rectangle.
#[inline(always)]
pub fn with_round_rectangle_tri_list_xy_f32_rgba_f32(
    resolution_corner: uint,
    m: &Matrix2d,
    rect: &Rectangle,
    round_radius: &f64,
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    let (x, y, w, h) = (rect[0], rect[1], rect[2], rect[3]);
    let radius = *round_radius;
    let n = resolution_corner * 4 + 4;
    let mut i = 0u;
    stream_polygon_tri_list_xy_f32_rgba_f32(m, || {
        if i >= n { return None; }

        let j = i;
        i += 1;
        match j {
            j if j >= resolution_corner * 3 => {
                let angle = j as f64 / (n - 3) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + w - radius, y + radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
            j if j >= resolution_corner * 2 => {
                let angle = j as f64 / (n - 2) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + radius, y + radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
            j if j >= resolution_corner * 1 => {
                let angle = j as f64 / (n - 1) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + radius, y + h - radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
            j => {
                let angle = j as f64 / (n - 0) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + w - radius, y + h - radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
        }
    }, color, f);
}

/// Streams a polygon into tri list with color per vertex.
/// Uses buffers that fit inside L1 cache.
pub fn stream_polygon_tri_list_xy_f32_rgba_f32(
    m: &Matrix2d,
    polygon: || -> Option<[f64, ..2]>,
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    let mut vertices: [f32, ..740] = [0.0, ..740];
    let mut colors: [f32, ..1480] = [0.0, ..1480];
    // Get the first point which will be used a lot.
    let fp = match polygon() { None => return, Some(val) => val };
    let (fx, fy) = (tx(m, fp[0], fp[1]), ty(m, fp[0], fp[1]));
    let gp = match polygon() { None => return, Some(val) => val };
    let (gx, gy) = (tx(m, gp[0], gp[1]), ty(m, gp[0], gp[1]));
    let mut gx = gx;
    let mut gy = gy;
    let mut i = 0;
    'read_vertices: loop {
        let ind_out = i * 2 * 3;
        vertices[ind_out + 0] = fx;
        vertices[ind_out + 1] = fy;
        let ind_out = i * 4 * 3;
        colors[ind_out + 0] = color[0];
        colors[ind_out + 1] = color[1];
        colors[ind_out + 2] = color[2];
        colors[ind_out + 3] = color[3];

        // Copy vertex.
        let ind_out = i * 2 * 3 + 2;
        let p =
            match polygon() {
                None => break 'read_vertices,
                Some(val) => val,
            };
        let x = tx(m, p[0], p[1]);
        let y = ty(m, p[0], p[1]);

        vertices[ind_out + 0] = gx;
        vertices[ind_out + 1] = gy;
        vertices[ind_out + 2] = x;
        vertices[ind_out + 3] = y;
        gx = x;
        gy = y;
        let ind_out = i * 4 * 3 + 4;
        colors[ind_out + 0] = color[0];
        colors[ind_out + 1] = color[1];
        colors[ind_out + 2] = color[2];
        colors[ind_out + 3] = color[3];
        colors[ind_out + 4] = color[0];
        colors[ind_out + 5] = color[1];
        colors[ind_out + 6] = color[2];
        colors[ind_out + 7] = color[3];

        i += 1;
        // Buffer is full.
        if i * 2 * 3 + 2 == vertices.len() {
            // Send chunk and start over.
            f(vertices.slice(0, i * 2 * 3),
                colors.slice(0, i * 4 * 3));
            i = 0;
        }
    }

    if i > 0 {
        f(vertices.slice(0, i * 2 * 3),
            colors.slice(0, i * 4 * 3));
    }
}

/// Splits polygon into convex segments with one color per vertex.
/// Create a buffer that fits into L1 cache with 1KB overhead.
pub fn with_polygon_tri_list_xy_f32_rgba_f32(
    m: &Matrix2d,
    polygon: &[f64],
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    let n = polygon.len();
    let mut i = 0;
    stream_polygon_tri_list_xy_f32_rgba_f32(
        m, || {
            if i >= n { return None; }

            let j = i;
            i += 2;
            Some([polygon[j], polygon[j+1]])
        }, color, f);
}

/// Creates triangle list vertices from rectangle.
pub fn rect_tri_list_xy_f32(m: &Matrix2d, rect: &Rectangle) -> [f32, ..12] {
    let (x, y, w, h) = (rect[0], rect[1], rect[2], rect[3]);
    let (x2, y2) = (x + w, y + h);
    [tx(m,x,y), ty(m,x,y), tx(m,x2,y), ty(m,x2,y), tx(m,x,y2), ty(m,x,y2),
     tx(m,x2,y), ty(m,x2,y), tx(m,x2,y2), ty(m,x2,y2), tx(m,x,y2), ty(m,x,y2)]
}

/// Creates triangle list colors from rectangle.
pub fn rect_tri_list_rgba_f32(color: [f32, ..4]) -> [f32, ..48] {
    let (r, g, b, a) = (color[0], color[1], color[2], color[3]);
    [r, g, b, a, // 0
     r, g, b, a, // 1
     r, g, b, a, // 2
     r, g, b, a, // 3
     r, g, b, a, // 4
     r, g, b, a, // 5
     r, g, b, a, // 6
     r, g, b, a, // 7
     r, g, b, a, // 8
     r, g, b, a, // 9
     r, g, b, a, // 10
     r, g, b, a]
}

/// Creates triangle list texture coords from image.
pub fn rect_tri_list_uv_f32(image: &Image) -> [f32, ..12] {
    let x1 = image.source_rect[0] as f32 / image.texture_width as f32;
    let y1 = image.source_rect[1] as f32 / image.texture_height as f32;
    let x2 = (image.source_rect[0] + image.source_rect[2]) as f32 / image.texture_width as f32;
    let y2 = (image.source_rect[1] + image.source_rect[3]) as f32 / image.texture_height as f32;
    [x1, y1, x2, y1, x1, y2,
     x2, y1, x2, y2, x1, y2]
}

<commit_msg>Working on `with_round_border_line_tri_list_xy_f32_rgba_f32`<commit_after>//! Methods for converting shapes into triangles.

use std;
use {
    Image,
    Line,
    Matrix2d,
    Rectangle,
};
use interpolation::{lerp};
use vecmath::{
    multiply,
    orient,
    translate,
};

#[inline(always)]
fn tx(m: &Matrix2d, x: f64, y: f64) -> f32 {
    (m[0] * x + m[1] * y + m[2]) as f32
}

#[inline(always)]
fn ty(m: &Matrix2d, x: f64, y: f64) -> f32 {
    (m[3] * x + m[4] * y + m[5]) as f32
}

/// Streams tweened polygons using linear interpolation.
#[inline(always)]
pub fn with_lerp_polygons_tri_list_xy_f32_rgba_f32(
    m: &Matrix2d,
    polygons: &[&[f64]],
    tween_factor: f64,
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    let poly_len = polygons.len() as f64;
    // Map to interval between 0 and 1.
    let tw = tween_factor % 1.0;
    // Map negative values to positive.
    let tw = if tw < 0.0 { tw + 1.0 } else { tw };
    // Map to frame.
    let tw = tw * poly_len;
    // Get the current frame.
    let frame = tw as uint;
    // Get the next frame.
    let next_frame = (frame + 1) % polygons.len();
    let p0 = polygons[frame];
    let p1 = polygons[next_frame];
    // Get factor between frames.
    let tw = tw - frame as f64;
    let n = polygons[0].len();
    let mut i = 0u;
    stream_polygon_tri_list_xy_f32_rgba_f32(m, || {
        if i >= n { return None; }

        let j = i;
        i += 2;
        let (x0, y0) = (p0[j], p0[j+1]);
        let (x1, y1) = (p1[j], p1[j+1]);
        Some([lerp(&x0, &x1, &tw), lerp(&y0, &y1, &tw)])
    }, color, f);
}

/// Streams an ellipse specified by a resolution.
#[inline(always)]
pub fn with_ellipse_tri_list_xy_f32_rgba_f32(
    resolution: uint,
    m: &Matrix2d,
    rect: &Rectangle,
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    let (x, y, w, h) = (rect[0], rect[1], rect[2], rect[3]);
    let (cw, ch) = (0.5 * w, 0.5 * h);
    let (cx, cy) = (x + cw, y + ch);
    let n = resolution;
    let mut i = 0u;
    stream_polygon_tri_list_xy_f32_rgba_f32(m, || {
        if i >= n { return None; }

        let angle = i as f64 / n as f64 * std::f64::consts::PI_2;
        i += 1;
        Some([cx + angle.cos() * cw, cy + angle.sin() * ch])
    }, color, f);
}

/// Streams a round border line.
#[inline(always)]
pub fn with_round_border_line_tri_list_xy_f32_rgba_f32(
    resolution_cap: uint,
    m: &Matrix2d,
    line: &Line,
    round_border_radius: &f64,
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    let radius = *round_border_radius;
    let (x1, y1, x2, y2) = (line[0], line[1], line[2], line[3]);
    let (dx, dy) = (x2 - x1, y2 - y1);
    let w = (dx * dx + dy * dy).sqrt();
    let m = multiply(m, &translate(x1, y1));
    let m = multiply(&m, &orient(dx, dy));
    let n = resolution_cap * 2 + 2;
    let mut i = 0u;
    stream_polygon_tri_list_xy_f32_rgba_f32(&m, || {
        if i >= n { return None; }

        let j = i;
        i += 1;
        match j {
            j if j >= resolution_cap => {
                let angle = j as f64 / (n - 1) as f64 * std::f64::consts::PI_2;
                Some([w + angle.cos() * radius, angle.sin() * radius])
            },
            j => {
                let angle = j as f64 / (n - 0) as f64 * std::f64::consts::PI_2;
                Some([angle.cos() * radius, angle.sin() * radius])
            },
        }
    }, color, f);
    /*
    let (x, y, w, h) = (rect[0], rect[1], rect[2], rect[3]);
    let radius = round_border[0];
    let n = resolution_corner * 4 + 4;
    let mut i = 0u;
    stream_polygon_tri_list_xy_f32_rgba_f32(m, || {
        if i >= n { return None; }

        let j = i;
        i += 1;
        match j {
            j if j >= resolution_corner * 3 => {
                let angle = j as f64 / (n - 3) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + w - radius, y + radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
            j if j >= resolution_corner * 2 => {
                let angle = j as f64 / (n - 2) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + radius, y + radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
            j if j >= resolution_corner * 1 => {
                let angle = j as f64 / (n - 1) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + radius, y + h - radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
            j => {
                let angle = j as f64 / (n - 0) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + w - radius, y + h - radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
        }
    }, color, f);
    */
}

/// Streams a round rectangle.
#[inline(always)]
pub fn with_round_rectangle_tri_list_xy_f32_rgba_f32(
    resolution_corner: uint,
    m: &Matrix2d,
    rect: &Rectangle,
    round_radius: &f64,
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    let (x, y, w, h) = (rect[0], rect[1], rect[2], rect[3]);
    let radius = *round_radius;
    let n = resolution_corner * 4 + 4;
    let mut i = 0u;
    stream_polygon_tri_list_xy_f32_rgba_f32(m, || {
        if i >= n { return None; }

        let j = i;
        i += 1;
        match j {
            j if j >= resolution_corner * 3 => {
                let angle = j as f64 / (n - 3) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + w - radius, y + radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
            j if j >= resolution_corner * 2 => {
                let angle = j as f64 / (n - 2) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + radius, y + radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
            j if j >= resolution_corner * 1 => {
                let angle = j as f64 / (n - 1) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + radius, y + h - radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
            j => {
                let angle = j as f64 / (n - 0) as f64 * std::f64::consts::PI_2;
                let (cx, cy) = (x + w - radius, y + h - radius);
                Some([cx + angle.cos() * radius, cy + angle.sin() * radius])
            },
        }
    }, color, f);
}

/// Streams a polygon into tri list with color per vertex.
/// Uses buffers that fit inside L1 cache.
pub fn stream_polygon_tri_list_xy_f32_rgba_f32(
    m: &Matrix2d,
    polygon: || -> Option<[f64, ..2]>,
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    let mut vertices: [f32, ..740] = [0.0, ..740];
    let mut colors: [f32, ..1480] = [0.0, ..1480];
    // Get the first point which will be used a lot.
    let fp = match polygon() { None => return, Some(val) => val };
    let (fx, fy) = (tx(m, fp[0], fp[1]), ty(m, fp[0], fp[1]));
    let gp = match polygon() { None => return, Some(val) => val };
    let (gx, gy) = (tx(m, gp[0], gp[1]), ty(m, gp[0], gp[1]));
    let mut gx = gx;
    let mut gy = gy;
    let mut i = 0;
    'read_vertices: loop {
        let ind_out = i * 2 * 3;
        vertices[ind_out + 0] = fx;
        vertices[ind_out + 1] = fy;
        let ind_out = i * 4 * 3;
        colors[ind_out + 0] = color[0];
        colors[ind_out + 1] = color[1];
        colors[ind_out + 2] = color[2];
        colors[ind_out + 3] = color[3];

        // Copy vertex.
        let ind_out = i * 2 * 3 + 2;
        let p =
            match polygon() {
                None => break 'read_vertices,
                Some(val) => val,
            };
        let x = tx(m, p[0], p[1]);
        let y = ty(m, p[0], p[1]);

        vertices[ind_out + 0] = gx;
        vertices[ind_out + 1] = gy;
        vertices[ind_out + 2] = x;
        vertices[ind_out + 3] = y;
        gx = x;
        gy = y;
        let ind_out = i * 4 * 3 + 4;
        colors[ind_out + 0] = color[0];
        colors[ind_out + 1] = color[1];
        colors[ind_out + 2] = color[2];
        colors[ind_out + 3] = color[3];
        colors[ind_out + 4] = color[0];
        colors[ind_out + 5] = color[1];
        colors[ind_out + 6] = color[2];
        colors[ind_out + 7] = color[3];

        i += 1;
        // Buffer is full.
        if i * 2 * 3 + 2 == vertices.len() {
            // Send chunk and start over.
            f(vertices.slice(0, i * 2 * 3),
                colors.slice(0, i * 4 * 3));
            i = 0;
        }
    }

    if i > 0 {
        f(vertices.slice(0, i * 2 * 3),
            colors.slice(0, i * 4 * 3));
    }
}

/// Splits polygon into convex segments with one color per vertex.
/// Create a buffer that fits into L1 cache with 1KB overhead.
pub fn with_polygon_tri_list_xy_f32_rgba_f32(
    m: &Matrix2d,
    polygon: &[f64],
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    let n = polygon.len();
    let mut i = 0;
    stream_polygon_tri_list_xy_f32_rgba_f32(
        m, || {
            if i >= n { return None; }

            let j = i;
            i += 2;
            Some([polygon[j], polygon[j+1]])
        }, color, f);
}

/// Creates triangle list vertices from rectangle.
pub fn rect_tri_list_xy_f32(m: &Matrix2d, rect: &Rectangle) -> [f32, ..12] {
    let (x, y, w, h) = (rect[0], rect[1], rect[2], rect[3]);
    let (x2, y2) = (x + w, y + h);
    [tx(m,x,y), ty(m,x,y), tx(m,x2,y), ty(m,x2,y), tx(m,x,y2), ty(m,x,y2),
     tx(m,x2,y), ty(m,x2,y), tx(m,x2,y2), ty(m,x2,y2), tx(m,x,y2), ty(m,x,y2)]
}

/// Creates triangle list colors from rectangle.
pub fn rect_tri_list_rgba_f32(color: [f32, ..4]) -> [f32, ..48] {
    let (r, g, b, a) = (color[0], color[1], color[2], color[3]);
    [r, g, b, a, // 0
     r, g, b, a, // 1
     r, g, b, a, // 2
     r, g, b, a, // 3
     r, g, b, a, // 4
     r, g, b, a, // 5
     r, g, b, a, // 6
     r, g, b, a, // 7
     r, g, b, a, // 8
     r, g, b, a, // 9
     r, g, b, a, // 10
     r, g, b, a]
}

/// Creates triangle list texture coords from image.
pub fn rect_tri_list_uv_f32(image: &Image) -> [f32, ..12] {
    let x1 = image.source_rect[0] as f32 / image.texture_width as f32;
    let y1 = image.source_rect[1] as f32 / image.texture_height as f32;
    let x2 = (image.source_rect[0] + image.source_rect[2]) as f32 / image.texture_width as f32;
    let y2 = (image.source_rect[1] + image.source_rect[3]) as f32 / image.texture_height as f32;
    [x1, y1, x2, y1, x1, y2,
     x2, y1, x2, y2, x1, y2]
}
<|endoftext|>


<commit_before>use nom::{self, IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::StreamProducer;

/// Represent the different kinds of errors.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ErrorKind {
  /// Error from I/O.
  IO(io::ErrorKind),
  /// A parser stopped midway and need more bytes to consume.
  Incomplete(usize),
  /// A parser has completes and there is still more bytes to consume.
  Continue,
  /// A parser has completes and there is no more bytes to consume.
  EndOfInput,
  /// A non-specified error.
  Unknown,
  // Parser Error
  /// Failed parsing the "fLaC" header token.
  HeaderParser,
  /// Failed parsing a metadata header.
  MetadataHeaderParser,
  /// Failed parsing the metadata block `StreamInfo`.
  StreamInfoParser,
  /// Failed parsing the metadata block `Padding`.
  PaddingParser,
  /// Failed parsing the metadata block `Application`.
  ApplicationParser,
  /// Failed parsing the metadata block `SeekTable`.
  SeekTableParser,
  /// Failed parsing the metadata block `VorbisComment`.
  VorbisCommentParser,
  /// Failed parsing the metadata block `CueSheet`.
  CueSheetParser,
  /// Failed parsing the metadata block `Picture`.
  PictureParser,
  /// Failed parsing the metadata block `Unknown`.
  UnknownParser,
  /// Failed parsing the blocking strategy inside the frame header.
  BlockingStrategyParser,
  /// Failed parsing the blocking sample inside the frame header.
  BlockingSampleParser,
  /// Failed parsing the channel bits inside the frame header.
  ChannelBitsParser,
  /// Failed parsing the UTF-8 header inside the frame header.
  UTF8HeaderParser,
  /// Failed parsing the UTF-8 body inside the frame header.
  UTF8BodyParser,
  /// Failed parsing the secondary block size inside the frame header.
  BlockSizeParser,
  /// Failed parsing the secondary sample rate inside the frame header.
  SampleRateParser,
  /// Failed parsing the CRC-8 inside the frame header.
  CRC8Parser,
  /// Failed parsing the frame footer, also known as the CRC-16.
  FrameFooterParser,
  /// Failed parsing the subframe header.
  SubframeHeaderParser,
  /// Failed parsing the leading zero for a unary value.
  LeadingZerosParser,
  /// Failed parsing a Constant subframe data.
  ConstantParser,
  /// Failed parsing a Verbatim subframe data.
  VerbatimParser,
  /// Failed parsing a Fixed subframe data.
  FixedParser,
  /// Failed parsing a LPC subframe data.
  LPCParser,
  // Invalid Error
  /// A block type, base on the number, that is outside the range (0-126).
  InvalidBlockType,
  /// An incorrect sync code with the frame header.
  InvalidSyncCode,
  /// A block sample that could cause sync-fooling.
  InvalidBlockSample,
  /// One or more bits are reserved values.
  InvalidChannelBits,
  /// An error occurred in building the UTF-8 value.
  InvalidUTF8,
  /// The stored CRC-8 doesn't match the one generated from the bytes within
  /// the frame header.
  InvalidCRC8,
  /// The stored CRC-16 doesn't match the one generated from the bytes
  /// within the entire frame.
  InvalidCRC16,
  /// A subframe header that could cause sync-fooling.
  InvalidSubframeHeader,
  // Not Found
  /// Some metadata block was not found with a specific filter.
  NotFound,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        match e {
          nom::Err::Code(k)               |
          nom::Err::Node(k, _)            |
          nom::Err::Position(k, _)        |
          nom::Err::NodePosition(k, _, _) => {
            if let nom::ErrorKind::Custom(kind) = k {
              Err(kind)
            } else {
              Err(ErrorKind::Unknown)
            }
          }
        }
      },
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T, ErrorKind>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      match e {
        nom::Err::Code(k)               |
        nom::Err::Node(k, _)            |
        nom::Err::Position(k, _)        |
        nom::Err::NodePosition(k, _, _) => {
          if let nom::ErrorKind::Custom(kind) = k {
            Err(kind)
          } else {
            Err(ErrorKind::Unknown)
          }
        }
      }
    },
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(|e| ErrorKind::IO(e.kind())));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::{self, IResult};

  #[inline]
  fn be_u32(input: &[u8]) -> IResult<&[u8], u32, ErrorKind> {
    nom::be_u32(input).map_err(to_custom_error!(Unknown))
  }

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<commit_msg>Use the new `to_custom_error!` interface for tests<commit_after>use nom::{self, IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::StreamProducer;

/// Represent the different kinds of errors.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ErrorKind {
  /// Error from I/O.
  IO(io::ErrorKind),
  /// A parser stopped midway and need more bytes to consume.
  Incomplete(usize),
  /// A parser has completes and there is still more bytes to consume.
  Continue,
  /// A parser has completes and there is no more bytes to consume.
  EndOfInput,
  /// A non-specified error.
  Unknown,
  // Parser Error
  /// Failed parsing the "fLaC" header token.
  HeaderParser,
  /// Failed parsing a metadata header.
  MetadataHeaderParser,
  /// Failed parsing the metadata block `StreamInfo`.
  StreamInfoParser,
  /// Failed parsing the metadata block `Padding`.
  PaddingParser,
  /// Failed parsing the metadata block `Application`.
  ApplicationParser,
  /// Failed parsing the metadata block `SeekTable`.
  SeekTableParser,
  /// Failed parsing the metadata block `VorbisComment`.
  VorbisCommentParser,
  /// Failed parsing the metadata block `CueSheet`.
  CueSheetParser,
  /// Failed parsing the metadata block `Picture`.
  PictureParser,
  /// Failed parsing the metadata block `Unknown`.
  UnknownParser,
  /// Failed parsing the blocking strategy inside the frame header.
  BlockingStrategyParser,
  /// Failed parsing the blocking sample inside the frame header.
  BlockingSampleParser,
  /// Failed parsing the channel bits inside the frame header.
  ChannelBitsParser,
  /// Failed parsing the UTF-8 header inside the frame header.
  UTF8HeaderParser,
  /// Failed parsing the UTF-8 body inside the frame header.
  UTF8BodyParser,
  /// Failed parsing the secondary block size inside the frame header.
  BlockSizeParser,
  /// Failed parsing the secondary sample rate inside the frame header.
  SampleRateParser,
  /// Failed parsing the CRC-8 inside the frame header.
  CRC8Parser,
  /// Failed parsing the frame footer, also known as the CRC-16.
  FrameFooterParser,
  /// Failed parsing the subframe header.
  SubframeHeaderParser,
  /// Failed parsing the leading zero for a unary value.
  LeadingZerosParser,
  /// Failed parsing a Constant subframe data.
  ConstantParser,
  /// Failed parsing a Verbatim subframe data.
  VerbatimParser,
  /// Failed parsing a Fixed subframe data.
  FixedParser,
  /// Failed parsing a LPC subframe data.
  LPCParser,
  // Invalid Error
  /// A block type, base on the number, that is outside the range (0-126).
  InvalidBlockType,
  /// An incorrect sync code with the frame header.
  InvalidSyncCode,
  /// A block sample that could cause sync-fooling.
  InvalidBlockSample,
  /// One or more bits are reserved values.
  InvalidChannelBits,
  /// An error occurred in building the UTF-8 value.
  InvalidUTF8,
  /// The stored CRC-8 doesn't match the one generated from the bytes within
  /// the frame header.
  InvalidCRC8,
  /// The stored CRC-16 doesn't match the one generated from the bytes
  /// within the entire frame.
  InvalidCRC16,
  /// A subframe header that could cause sync-fooling.
  InvalidSubframeHeader,
  // Not Found
  /// Some metadata block was not found with a specific filter.
  NotFound,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        match e {
          nom::Err::Code(k)               |
          nom::Err::Node(k, _)            |
          nom::Err::Position(k, _)        |
          nom::Err::NodePosition(k, _, _) => {
            if let nom::ErrorKind::Custom(kind) = k {
              Err(kind)
            } else {
              Err(ErrorKind::Unknown)
            }
          }
        }
      },
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T, ErrorKind>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      match e {
        nom::Err::Code(k)               |
        nom::Err::Node(k, _)            |
        nom::Err::Position(k, _)        |
        nom::Err::NodePosition(k, _, _) => {
          if let nom::ErrorKind::Custom(kind) = k {
            Err(kind)
          } else {
            Err(ErrorKind::Unknown)
          }
        }
      }
    },
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(|e| ErrorKind::IO(e.kind())));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::{self, IResult};

  #[inline]
  fn be_u32(input: &[u8]) -> IResult<&[u8], u32, ErrorKind> {
    to_custom_error!(input, nom::be_u32, Unknown)
  }

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<|endoftext|>


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

use csv;
use fst::{IntoStreamer, Streamer};
use fst::raw::Output;

use Error;

pub fn escape_input(b: u8) -> String {
    String::from_utf8(ascii::escape_default(b).collect::<Vec<_>>()).unwrap()
}

pub fn get_buf_reader<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<io::BufReader<Box<io::Read + Send + Sync + 'static>>> {
    Ok(io::BufReader::new(get_reader(path)?))
}

pub fn get_buf_writer<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<io::BufWriter<Box<io::Write + Send + Sync + 'static>>> {
    Ok(io::BufWriter::new(get_writer(path)?))
}

pub fn get_reader<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<Box<io::Read + Send + Sync + 'static>> {
    Ok(match to_stdio(path) {
        None => Box::new(io::stdin()),
        Some(path) => Box::new(File::open(path)?),
    })
}

pub fn get_writer<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<Box<io::Write + Send + Sync + 'static>> {
    Ok(match to_stdio(path) {
        None => Box::new(io::stdout()),
        Some(path) => Box::new(File::create(path)?),
    })
}

fn to_stdio<T: AsRef<Path>>(path: Option<T>) -> Option<PathBuf> {
    match path {
        None => None,
        Some(s) => {
            if s.as_ref().to_string_lossy() == "-" {
                None
            } else {
                Some(s.as_ref().to_path_buf())
            }
        }
    }
}

pub fn print_stream<'f, W, I, S>(
    mut wtr: W,
    outputs: bool,
    stream: I,
) -> Result<(), Error>
where W: io::Write,
      I: for<'a> IntoStreamer<'a, Into=S, Item=(&'a [u8], Output)>,
      S: 'f + for<'a> Streamer<'a, Item=(&'a [u8], Output)> {
    let mut stream = stream.into_stream();
    if outputs {
        let mut wtr = csv::Writer::from_writer(wtr);
        while let Some((k, v)) = stream.next() {
            let v = v.value().to_string();
            wtr.write_record((&[k, v.as_bytes()]).iter())?;
        }
        wtr.flush().map_err(From::from)
    } else {
        while let Some((k, _)) = stream.next() {
            wtr.write_all(k)?;
            wtr.write_all(b"\n")?;
        }
        wtr.flush().map_err(From::from)
    }
}

pub struct ConcatLines {
    inputs: Vec<PathBuf>,
    cur: Option<Lines>,
}

type Lines = io::Lines<io::BufReader<Box<io::Read + Send + Sync + 'static>>>;

impl ConcatLines {
    pub fn new(mut inputs: Vec<PathBuf>) -> ConcatLines {
        inputs.reverse(); // treat it as a stack
        ConcatLines { inputs: inputs, cur: None }
    }
}

impl Iterator for ConcatLines {
    type Item = io::Result<String>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.cur.is_none() {
                match self.inputs.pop() {
                    None => return None,
                    Some(path) => {
                        let rdr = match get_buf_reader(Some(path)) {
                            Err(err) => return Some(Err(err)),
                            Ok(rdr) => rdr,
                        };
                        self.cur = Some(rdr.lines());
                    }
                }
            }
            match self.cur.as_mut().and_then(|lines| Iterator::next(lines)) {
                None => self.cur = None,
                Some(r) => return Some(r),
            }
        }
    }
}

pub struct ConcatCsv {
    inputs: Vec<PathBuf>,
    cur: Option<Rows>,
}

type Reader = Box<io::Read + Send + Sync + 'static>;
type Rows = csv::DeserializeRecordsIntoIter<Reader, (String, u64)>;

impl ConcatCsv {
    pub fn new(mut inputs: Vec<PathBuf>) -> ConcatCsv {
        inputs.reverse(); // treat it as a stack
        ConcatCsv { inputs: inputs, cur: None }
    }

    fn read_row(&mut self) -> Option<Result<(String, u64), Error>> {
        let rdr = match self.cur {
            None => return None,
            Some(ref mut rdr) => rdr,
        };
        match rdr.next() {
            Some(Ok((k, v))) => Some(Ok((k, v))),
            Some(Err(err)) => Some(Err(From::from(err))),
            None => None,
        }
    }
}

impl Iterator for ConcatCsv {
    type Item = Result<(String, u64), Error>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.cur.is_none() {
                match self.inputs.pop() {
                    None => return None,
                    Some(path) => {
                        let rdr = match get_reader(Some(path)) {
                            Err(err) => return Some(Err(From::from(err))),
                            Ok(rdr) => rdr,
                        };
                        let csvrdr = csv::Reader::from_reader(rdr);
                        self.cur = Some(csvrdr.into_deserialize());
                    }
                }
            }
            match self.read_row() {
                None => self.cur = None,
                Some(r) => return Some(r),
            }
        }
    }
}
<commit_msg>fst-bin: don't skip headers<commit_after>use std::ascii;
use std::fs::File;
use std::io::{self, BufRead};
use std::path::{Path, PathBuf};

use csv;
use fst::{IntoStreamer, Streamer};
use fst::raw::Output;

use Error;

pub fn escape_input(b: u8) -> String {
    String::from_utf8(ascii::escape_default(b).collect::<Vec<_>>()).unwrap()
}

pub fn get_buf_reader<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<io::BufReader<Box<io::Read + Send + Sync + 'static>>> {
    Ok(io::BufReader::new(get_reader(path)?))
}

pub fn get_buf_writer<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<io::BufWriter<Box<io::Write + Send + Sync + 'static>>> {
    Ok(io::BufWriter::new(get_writer(path)?))
}

pub fn get_reader<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<Box<io::Read + Send + Sync + 'static>> {
    Ok(match to_stdio(path) {
        None => Box::new(io::stdin()),
        Some(path) => Box::new(File::open(path)?),
    })
}

pub fn get_writer<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<Box<io::Write + Send + Sync + 'static>> {
    Ok(match to_stdio(path) {
        None => Box::new(io::stdout()),
        Some(path) => Box::new(File::create(path)?),
    })
}

fn to_stdio<T: AsRef<Path>>(path: Option<T>) -> Option<PathBuf> {
    match path {
        None => None,
        Some(s) => {
            if s.as_ref().to_string_lossy() == "-" {
                None
            } else {
                Some(s.as_ref().to_path_buf())
            }
        }
    }
}

pub fn print_stream<'f, W, I, S>(
    mut wtr: W,
    outputs: bool,
    stream: I,
) -> Result<(), Error>
where W: io::Write,
      I: for<'a> IntoStreamer<'a, Into=S, Item=(&'a [u8], Output)>,
      S: 'f + for<'a> Streamer<'a, Item=(&'a [u8], Output)> {
    let mut stream = stream.into_stream();
    if outputs {
        let mut wtr = csv::Writer::from_writer(wtr);
        while let Some((k, v)) = stream.next() {
            let v = v.value().to_string();
            wtr.write_record((&[k, v.as_bytes()]).iter())?;
        }
        wtr.flush().map_err(From::from)
    } else {
        while let Some((k, _)) = stream.next() {
            wtr.write_all(k)?;
            wtr.write_all(b"\n")?;
        }
        wtr.flush().map_err(From::from)
    }
}

pub struct ConcatLines {
    inputs: Vec<PathBuf>,
    cur: Option<Lines>,
}

type Lines = io::Lines<io::BufReader<Box<io::Read + Send + Sync + 'static>>>;

impl ConcatLines {
    pub fn new(mut inputs: Vec<PathBuf>) -> ConcatLines {
        inputs.reverse(); // treat it as a stack
        ConcatLines { inputs: inputs, cur: None }
    }
}

impl Iterator for ConcatLines {
    type Item = io::Result<String>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.cur.is_none() {
                match self.inputs.pop() {
                    None => return None,
                    Some(path) => {
                        let rdr = match get_buf_reader(Some(path)) {
                            Err(err) => return Some(Err(err)),
                            Ok(rdr) => rdr,
                        };
                        self.cur = Some(rdr.lines());
                    }
                }
            }
            match self.cur.as_mut().and_then(|lines| Iterator::next(lines)) {
                None => self.cur = None,
                Some(r) => return Some(r),
            }
        }
    }
}

pub struct ConcatCsv {
    inputs: Vec<PathBuf>,
    cur: Option<Rows>,
}

type Reader = Box<io::Read + Send + Sync + 'static>;
type Rows = csv::DeserializeRecordsIntoIter<Reader, (String, u64)>;

impl ConcatCsv {
    pub fn new(mut inputs: Vec<PathBuf>) -> ConcatCsv {
        inputs.reverse(); // treat it as a stack
        ConcatCsv { inputs: inputs, cur: None }
    }

    fn read_row(&mut self) -> Option<Result<(String, u64), Error>> {
        let rdr = match self.cur {
            None => return None,
            Some(ref mut rdr) => rdr,
        };
        match rdr.next() {
            Some(Ok((k, v))) => Some(Ok((k, v))),
            Some(Err(err)) => Some(Err(From::from(err))),
            None => None,
        }
    }
}

impl Iterator for ConcatCsv {
    type Item = Result<(String, u64), Error>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.cur.is_none() {
                match self.inputs.pop() {
                    None => return None,
                    Some(path) => {
                        let rdr = match get_reader(Some(path)) {
                            Err(err) => return Some(Err(From::from(err))),
                            Ok(rdr) => rdr,
                        };
                        let csvrdr = csv::ReaderBuilder::new()
                            .has_headers(false)
                            .from_reader(rdr);
                        self.cur = Some(csvrdr.into_deserialize());
                    }
                }
            }
            match self.read_row() {
                None => self.cur = None,
                Some(r) => return Some(r),
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::rand::{Rng, SeedableRng};
use std::num;

static LCG_MULTIPLIER: u32 = 1103515245;
static LCG_INCREMENT: u32 = 12345;
static LCG_MODULOUS: u32 = 2147483647; // 2 ** 31 - 1
static LCG_DEFAULT_SEED: u32 = 1;

struct LinearCongruentialPRNG {
    seed: u32,
    rand_state: u32
}

impl LinearCongruentialPRNG {
    fn new_unseeded() -> LinearCongruentialPRNG {
        LinearCongruentialPRNG { seed: LCG_DEFAULT_SEED, rand_state: LCG_DEFAULT_SEED }
    }
}

impl Rng for LinearCongruentialPRNG {
    fn next_u32(&mut self) -> u32 {
        let next_rand = ((self.rand_state * LCG_MULTIPLIER) + LCG_INCREMENT) & LCG_MODULOUS;
        self.rand_state = next_rand;
        next_rand
    }
}

impl SeedableRng<u32> for LinearCongruentialPRNG {
    fn reseed(&mut self, seed: u32) {
        self.seed =
            if seed == 0 {
                1
            } else {
                seed
            }
    }

    fn from_seed(seed: u32) -> LinearCongruentialPRNG {
        LinearCongruentialPRNG { seed: seed, rand_state: seed }
    }
}

enum PRNG {
    LinearCongruentialPRNG,
}

fn main() {
    let mut rng = LinearCongruentialPRNG::new_unseeded();
    for _ in range(0u, 20) {
        println!("Rand num {}", rng.next_u32() % 100);
    }
}

#[test]
fn LCG_test() {
}
<commit_msg>trivial linear feedback shift register implementation<commit_after>use std::rand::{Rng, SeedableRng};

static LCG_MULTIPLIER: u32 = 1103515245;
static LCG_INCREMENT: u32 = 12345;
static LCG_MODULOUS: u32 = 2147483647; // 2 ** 31 - 1
static LCG_DEFAULT_SEED: u32 = 1;

struct LinearCongruentialPRNG {
    seed: u32,
    rand_state: u32
}

impl LinearCongruentialPRNG {
    fn new_unseeded() -> LinearCongruentialPRNG {
        LinearCongruentialPRNG { seed: LCG_DEFAULT_SEED, rand_state: LCG_DEFAULT_SEED }
    }
}

impl Rng for LinearCongruentialPRNG {
    fn next_u32(&mut self) -> u32 {
        let next_rand = ((self.rand_state * LCG_MULTIPLIER) + LCG_INCREMENT) & LCG_MODULOUS;
        self.rand_state = next_rand;
        next_rand
    }
}

impl SeedableRng<u32> for LinearCongruentialPRNG {
    fn reseed(&mut self, seed: u32) {
        self.seed =
            if seed == 0 {
                1
            } else {
                seed
            }
    }

    fn from_seed(seed: u32) -> LinearCongruentialPRNG {
        LinearCongruentialPRNG { seed: seed, rand_state: seed }
    }
}

struct LinearFeedbackShiftRegisterPRNG {
    front_ptr: *mut u32,
    rear_ptr:  *mut u32,
    end_ptr: *mut u32,
    iv: Vec<u32>
}

impl LinearFeedbackShiftRegisterPRNG {
    fn init_seed_info(seed: &Vec<u32>) -> (*mut u32, *mut u32, *mut u32, Vec<u32>, u32) {
        let mut iv = seed.clone();

        let (deg, shift_sep) = match std::mem::size_of_val(&iv) {
            // x ** 7 + x** 3 + 1
            x if x < 64 => (7u, 3u),
            // x**15 + x + 1.
            x if x < 128 => (15u, 1u),
            // x**31 + x**3 + 1.
            x if x < 256 => (31u, 3u),
            // x**63 + x + 1.
            _ => (63u, 1u)
        };

        for i in range(1u, deg + 1u) {
            let word = (16807 * iv[i-1]) % 2147483647;
            *iv.get_mut(i) = word as u32;
        }

        let front_ptr = unsafe{ iv.as_mut_ptr().offset(shift_sep as int) };
        let rear_ptr = unsafe{ iv.as_mut_ptr().offset(0) };
        let end_ptr = unsafe{ iv.as_mut_ptr().offset(deg as int) };
        (front_ptr, rear_ptr, end_ptr, iv, deg as u32)
    }
}

impl Rng for LinearFeedbackShiftRegisterPRNG {
    fn next_u32(&mut self) -> u32 {
        let (mut front_ptr, mut rear_ptr, end_ptr) = (self.front_ptr, self.rear_ptr, self.end_ptr);

        let next_rand: u32 = unsafe{ ((*front_ptr + *rear_ptr) >> 1) & 0x7fffffff };

        front_ptr = unsafe{ front_ptr.offset(1) };
        if front_ptr >= end_ptr {
            front_ptr = self.iv.as_mut_ptr();
            rear_ptr = unsafe{ rear_ptr.offset(1) };
        } else {
            rear_ptr = unsafe{ rear_ptr.offset(1) };
            if rear_ptr >= end_ptr {
                rear_ptr = self.iv.as_mut_ptr();
            }
        }

        self.front_ptr = front_ptr;
        self.rear_ptr = rear_ptr;

        next_rand
    }
}

impl SeedableRng<Vec<u32>> for LinearFeedbackShiftRegisterPRNG {
    fn reseed(&mut self, seed: Vec<u32>) {
        let reseed_info = LinearFeedbackShiftRegisterPRNG::init_seed_info(&seed);
        self.front_ptr = reseed_info.clone().val0();
        self.rear_ptr = reseed_info.clone().val1();
        self.end_ptr = reseed_info.clone().val2();
        self.iv = reseed_info.clone().val3();

        let deg = reseed_info.clone().val4();

        for _ in range(0, (deg + 1) * 10) {
            let _ = self.next_u32();
        }
    }

    fn from_seed(seed: Vec<u32>) -> LinearFeedbackShiftRegisterPRNG {
        let (front_ptr, rear_ptr, end_ptr, iv, deg) = LinearFeedbackShiftRegisterPRNG::init_seed_info(&seed);

        let mut rng = LinearFeedbackShiftRegisterPRNG{
            front_ptr: front_ptr, rear_ptr: rear_ptr, end_ptr: end_ptr, iv: iv
        };

        for _ in range(0, (deg + 1) * 10) {
            rng.next_u32();
        }

        rng
    }
}

enum PRNG {
    LinearCongruentialPRNG,
    LinearFeedbackShiftRegisterPRNG
}

fn main() {
    let mut rng: LinearCongruentialPRNG = SeedableRng::from_seed(5);
    for _ in range(0u, 10) {
        println!("Rand num {}", rng.next_u32() % 100);
    }

    println!("\n");

    rng.reseed(434);
    for _ in range(0u, 10) {
        println!("Rand num {}", rng.next_u32() % 100);
    }

    println!("\n\n");

    let seed: Vec<u32> = range(9, 43).collect();
    let mut rng: LinearFeedbackShiftRegisterPRNG = SeedableRng::from_seed(seed);
    for _ in range(0u, 10) {
        println!("Rand num {}", rng.next_u32() % 100);
    }
}

#[test]
fn LCG_test() {
}
<|endoftext|>


<commit_before><commit_msg>upgraded the test to try a few other options including mix+match window sizes<commit_after><|endoftext|>


<commit_before>
extern "C" {
    #[no_mangle]
    pub(crate) fn pow(_: f64, _: f64) -> f64;
    #[no_mangle]
    fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: u64) -> *mut libc::c_void;
    #[no_mangle]
    fn fabs(_: f64) -> f64;
    #[no_mangle]
    fn j1(_: f64) -> f64;
    #[no_mangle]
    fn fmin(_: f64, _: f64) -> f64;
    #[no_mangle]
    fn ceil(_: f64) -> f64;
    #[no_mangle]
    fn floor(_: f64) -> f64;
    #[no_mangle]
    fn fmax(_: f64, _: f64) -> f64;
    #[no_mangle]
    fn sqrt(_: f64) -> f64;
    #[no_mangle]
    fn exp(_: f64) -> f64;
    #[no_mangle]
    fn memset(_: *mut libc::c_void, _: i32, _: u64) -> *mut libc::c_void;
}

pub const BESSEL_01: unsafe extern "C" fn(_: f64) -> f64 = j1;
pub const IR_PI: f64 = 3.1415926535897932384626433832795f64;
#[inline]
unsafe fn int_max(a: i32, b: i32) -> i32 {
    return if a >= b { a } else { b };
}
#[inline]
unsafe fn int_min(a: i32, b: i32) -> i32 {
    return if a <= b { a } else { b };
}

#[inline]
pub unsafe fn ir_gaussian(x: f64, std_dev: f64) -> f64 {
    return exp(-x * x / (2 as i32 as f64 * std_dev * std_dev))
        / (sqrt(2 as i32 as f64 * IR_PI) * std_dev);
}

#[derive(Copy, Clone)]
#[repr(C)]
pub union UnionU32F32 {
    pub i: u32,
    pub f: f32,
}

#[inline]
unsafe fn fastpow2(p: f32) -> f32 {
    let offset: f32 = if p < 0 as i32 as f32 { 1.0f32 } else { 0.0f32 };
    let clipp: f32 = if p < -(126 as i32) as f32 {
        -126.0f32
    } else {
        p
    };
    let w: i32 = clipp as i32;
    let z: f32 = clipp - w as f32 + offset;
    let v: UnionU32F32= UnionU32F32{
        i: (((1 as i32) << 23 as i32) as f32
            * (clipp + 121.2740575f32 + 27.7280233f32 / (4.84252568f32 - z) - 1.49012907f32 * z))
            as u32,
    };
    return v.f;
}
#[inline]
unsafe fn fastlog2(x: f32) -> f32 {
    let vx: UnionU32F32 = UnionU32F32 { f: x };
    let mx: UnionU32F32 = UnionU32F32 {
        i: vx.i & 0x7fffff as i32 as u32 | 0x3f000000 as i32 as u32,
    };
    let mut y: f32 = vx.i as f32;
    y *= 1.1920928955078125e-7f32;
    return y - 124.22551499f32 - 1.498030302f32 * mx.f - 1.72587999f32 / (0.3520887068f32 + mx.f);
}
#[inline]
pub(crate) unsafe fn fastpow(x: f32, p: f32) -> f32 {
    return fastpow2(p * fastlog2(x));
}
<commit_msg>Fix warnings and remove unused functions in math module<commit_after>
extern "C" {
    pub(crate) fn pow(_: f64, _: f64) -> f64;
    fn fabs(_: f64) -> f64;
    fn j1(_: f64) -> f64;
    fn fmin(_: f64, _: f64) -> f64;
    fn ceil(_: f64) -> f64;
    fn floor(_: f64) -> f64;
    fn fmax(_: f64, _: f64) -> f64;
    fn sqrt(_: f64) -> f64;
    fn exp(_: f64) -> f64;
}

pub const IR_PI: f64 = std::f64::consts::PI;
#[inline]
unsafe fn int_max(a: i32, b: i32) -> i32 {
    return if a >= b { a } else { b };
}
#[inline]
unsafe fn int_min(a: i32, b: i32) -> i32 {
    return if a <= b { a } else { b };
}

#[inline]
pub unsafe fn ir_gaussian(x: f64, std_dev: f64) -> f64 {
    return exp(-x * x / (2 as i32 as f64 * std_dev * std_dev))
        / (sqrt(2 as i32 as f64 * IR_PI) * std_dev);
}

#[derive(Copy, Clone)]
#[repr(C)]
pub union UnionU32F32 {
    pub i: u32,
    pub f: f32,
}

#[inline]
unsafe fn fastpow2(p: f32) -> f32 {
    let offset: f32 = if p < 0 as i32 as f32 { 1.0f32 } else { 0.0f32 };
    let clipp: f32 = if p < -(126 as i32) as f32 {
        -126.0f32
    } else {
        p
    };
    let w: i32 = clipp as i32;
    let z: f32 = clipp - w as f32 + offset;
    let v: UnionU32F32= UnionU32F32{
        i: (((1 as i32) << 23 as i32) as f32
            * (clipp + 121.2740575f32 + 27.7280233f32 / (4.84252568f32 - z) - 1.49012907f32 * z))
            as u32,
    };
    return v.f;
}
#[inline]
unsafe fn fastlog2(x: f32) -> f32 {
    let vx: UnionU32F32 = UnionU32F32 { f: x };
    let mx: UnionU32F32 = UnionU32F32 {
        i: vx.i & 0x7fffff as i32 as u32 | 0x3f000000 as i32 as u32,
    };
    let mut y: f32 = vx.i as f32;
    y *= 1.1920928955078125e-7f32;
    return y - 124.22551499f32 - 1.498030302f32 * mx.f - 1.72587999f32 / (0.3520887068f32 + mx.f);
}
#[inline]
pub(crate) unsafe fn fastpow(x: f32, p: f32) -> f32 {
    return fastpow2(p * fastlog2(x));
}
<|endoftext|>