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