#![allow(unused_must_use)]
extern crate gcc;
extern crate rustc_cfg;
extern crate num_bigint;
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use num_bigint::BigUint;
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("bases_table.rs");
let mut f = File::create(&dest_path).unwrap();
gen_bases(&mut f);
if let Ok(_) = env::var("CARGO_FEATURE_ASM") {
compile_asm();
}
}
fn compile_asm() {
if let Ok(target) = env::var("TARGET") {
if let Ok(host) = env::var("HOST") {
if host != target { panic!("Cross compiling not currently supported"); }
if (target.contains("x86-64") || target.contains("x86_64")) && target.contains("linux") {
let asm_srcs = &[
"src/ll/asm/addsub_n.S",
"src/ll/asm/mul_1.S",
"src/ll/asm/addmul_1.S",
];
gcc::compile_library("libasm.a", asm_srcs);
println!("cargo:rustc-cfg=asm");
}
}
}
}
fn gen_bases(f: &mut File) {
let limb_size = get_target_limb_size();
f.write_all(b"static BASES : [Base; 257] = [
/* 0 */ Base { digits_per_limb: 0, big_base: ::ll::limb::Limb(0) },
/* 1 */ Base { digits_per_limb: 0, big_base: ::ll::limb::Limb(0) },\n");
for i in 2..257 {
gen_base(f, limb_size, i);
}
f.write_all(b"];\n");
}
fn gen_base(f: &mut File, limb_size: usize, base: usize) {
let mut digits_per_limb = 1;
let base_as_bigint:BigUint = base.into();
let mut big_base:BigUint = base_as_bigint.clone();
loop {
let base_big_base = big_base.clone() * &base_as_bigint;
if base_big_base.bits() > limb_size {
if base_big_base == BigUint::from(1usize) << limb_size {
digits_per_limb += 1;
}
break;
}
digits_per_limb +=1;
big_base = base_big_base;
}
if base.is_power_of_two() {
big_base = base.trailing_zeros().into();
}
writeln!(f, " /* {:3} */ Base {{ digits_per_limb: {}, big_base: ::ll::limb::Limb(0x{:x}) }},",
base, digits_per_limb, big_base);
}
fn get_target_limb_size() -> usize {
let cfg = rustc_cfg::Cfg::new(env::var_os("TARGET").unwrap()).unwrap();
return cfg.target_pointer_width.parse().unwrap();
}