blob: 3daed5e8d336eeb9bfd83b89d96a17b899bf6564 [file] [log] [blame]
Yiming Jingcf21fc42021-07-16 13:23:26 -07001use std::env;
2use std::error::Error;
3use std::fs::File;
4use std::io::Write;
5use std::path::Path;
6
7fn main() {
8 let pointer_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH");
9 let u64_digit = pointer_width.as_ref().map(String::as_str) == Ok("64");
10 if u64_digit {
11 autocfg::emit("u64_digit");
12 }
13 let ac = autocfg::new();
14 let std = if ac.probe_sysroot_crate("std") {
15 "std"
16 } else {
17 "core"
18 };
19 if ac.probe_path(&format!("{}::convert::TryFrom", std)) {
20 autocfg::emit("has_try_from");
21 }
22
23 if let Ok(target_arch) = env::var("CARGO_CFG_TARGET_ARCH") {
24 if target_arch == "x86_64" || target_arch == "x86" {
25 let digit = if u64_digit { "u64" } else { "u32" };
26
27 let addcarry = format!("{}::arch::{}::_addcarry_{}", std, target_arch, digit);
28 if ac.probe_path(&addcarry) {
29 autocfg::emit("use_addcarry");
30 }
31 }
32 }
33
34 autocfg::rerun_path("build.rs");
35
36 write_radix_bases().unwrap();
37}
38
39/// Write tables of the greatest power of each radix for the given bit size. These are returned
40/// from `biguint::get_radix_base` to batch the multiplication/division of radix conversions on
41/// full `BigUint` values, operating on primitive integers as much as possible.
42///
43/// e.g. BASES_16[3] = (59049, 10) // 3¹⁰ fits in u16, but 3¹¹ is too big
44/// BASES_32[3] = (3486784401, 20)
45/// BASES_64[3] = (12157665459056928801, 40)
46///
47/// Powers of two are not included, just zeroed, as they're implemented with shifts.
48fn write_radix_bases() -> Result<(), Box<dyn Error>> {
49 let out_dir = env::var("OUT_DIR")?;
50 let dest_path = Path::new(&out_dir).join("radix_bases.rs");
51 let mut f = File::create(&dest_path)?;
52
53 for &bits in &[16, 32, 64] {
54 let max = if bits < 64 {
55 (1 << bits) - 1
56 } else {
57 std::u64::MAX
58 };
59
60 writeln!(f, "#[deny(overflowing_literals)]")?;
61 writeln!(
62 f,
63 "pub(crate) static BASES_{bits}: [(u{bits}, usize); 257] = [",
64 bits = bits
65 )?;
66 for radix in 0u64..257 {
67 let (base, power) = if radix == 0 || radix.is_power_of_two() {
68 (0, 0)
69 } else {
70 let mut power = 1;
71 let mut base = radix;
72
73 while let Some(b) = base.checked_mul(radix) {
74 if b > max {
75 break;
76 }
77 base = b;
78 power += 1;
79 }
80 (base, power)
81 };
82 writeln!(f, " ({}, {}), // {}", base, power, radix)?;
83 }
84 writeln!(f, "];")?;
85 }
86
87 Ok(())
88}