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