| use std::env; |
| use std::error::Error; |
| use std::fs::File; |
| use std::io::Write; |
| use std::path::Path; |
| |
| fn main() { |
| let ptr_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH"); |
| let u64_digit = ptr_width |
| .as_ref() |
| .map(|x| x == "64" || x == "128") |
| .unwrap_or(false); |
| |
| if u64_digit { |
| autocfg::emit("u64_digit"); |
| } |
| |
| let ac = autocfg::new(); |
| let std = if ac.probe_sysroot_crate("std") { |
| "std" |
| } else { |
| "core" |
| }; |
| |
| if ac.probe_path(&format!("{}::convert::TryFrom", std)) { |
| autocfg::emit("has_try_from"); |
| } |
| |
| if let Ok(arch) = env::var("CARGO_CFG_TARGET_ARCH") { |
| if arch == "x86_64" || arch == "x86" { |
| let digit = if u64_digit { "u64" } else { "u32" }; |
| |
| let addcarry = format!("{}::arch::{}::_addcarry_{}", std, arch, digit); |
| if ac.probe_path(&addcarry) { |
| autocfg::emit("use_addcarry"); |
| } |
| } |
| } |
| |
| // autocfg generates probe files in $OUT_DIR with nondeterministic contents. |
| // (In autocfg 1.4, the filenames are nondeterministic as well.) |
| let out_dir_env = env::var("OUT_DIR").unwrap(); |
| let out_dir = Path::new(&out_dir_env); |
| std::fs::remove_file(out_dir.join("probe0.ll")).unwrap(); |
| std::fs::remove_file(out_dir.join("probe1.ll")).unwrap(); |
| std::fs::remove_file(out_dir.join("probe2.ll")).unwrap(); |
| std::fs::remove_file(out_dir.join("probe3.ll")).unwrap(); |
| |
| autocfg::rerun_path("build.rs"); |
| |
| write_radix_bases().unwrap(); |
| } |
| |
| /// Write tables of the greatest power of each radix for the given bit size. These are returned |
| /// from `biguint::get_radix_base` to batch the multiplication/division of radix conversions on |
| /// full `BigUint` values, operating on primitive integers as much as possible. |
| /// |
| /// e.g. BASES_16[3] = (59049, 10) // 3¹⁰ fits in u16, but 3¹¹ is too big |
| /// BASES_32[3] = (3486784401, 20) |
| /// BASES_64[3] = (12157665459056928801, 40) |
| /// |
| /// Powers of two are not included, just zeroed, as they're implemented with shifts. |
| fn write_radix_bases() -> Result<(), Box<dyn Error>> { |
| let out_dir = env::var("OUT_DIR")?; |
| let dest_path = Path::new(&out_dir).join("radix_bases.rs"); |
| let mut f = File::create(&dest_path)?; |
| |
| for &bits in &[16, 32, 64] { |
| let max = if bits < 64 { |
| (1 << bits) - 1 |
| } else { |
| std::u64::MAX |
| }; |
| |
| writeln!(f, "#[deny(overflowing_literals)]")?; |
| writeln!( |
| f, |
| "pub(crate) static BASES_{bits}: [(u{bits}, usize); 257] = [", |
| bits = bits |
| )?; |
| for radix in 0u64..257 { |
| let (base, power) = if radix == 0 || radix.is_power_of_two() { |
| (0, 0) |
| } else { |
| let mut power = 1; |
| let mut base = radix; |
| |
| while let Some(b) = base.checked_mul(radix) { |
| if b > max { |
| break; |
| } |
| base = b; |
| power += 1; |
| } |
| (base, power) |
| }; |
| writeln!(f, " ({}, {}), // {}", base, power, radix)?; |
| } |
| writeln!(f, "];")?; |
| } |
| |
| Ok(()) |
| } |