build.rs 2.7 KB

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