diff --git a/build.rs b/build.rs index f2124b43f..2b7815ee4 100644 --- a/build.rs +++ b/build.rs @@ -3,18 +3,28 @@ use std::env; fn main() { println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rustc-check-cfg=cfg(limb_width_32)"); - println!("cargo:rustc-check-cfg=cfg(limb_width_64)"); + println!("cargo:rustc-check-cfg=cfg(arithmetic32)"); + println!("cargo:rustc-check-cfg=cfg(arithmetic64)"); - // Decide ideal limb width for arithmetic in the float parser. Refer to - // src/lexical/math.rs for where this has an effect. - let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); - match target_arch.as_str() { - "aarch64" | "mips64" | "powerpc64" | "x86_64" | "loongarch64" => { - println!("cargo:rustc-cfg=limb_width_64"); - } - _ => { - println!("cargo:rustc-cfg=limb_width_32"); - } + // Decide ideal limb width for arithmetic in the float parser and string + // parser. + let target_arch = env::var_os("CARGO_CFG_TARGET_ARCH").unwrap(); + let target_pointer_width = env::var_os("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap(); + if target_arch == "aarch64" + || target_arch == "loongarch64" + || target_arch == "mips64" + || target_arch == "powerpc64" + || target_arch == "wasm32" + || target_arch == "x86_64" + || target_pointer_width == "64" + { + // The above list of architectures are ones that have native support for + // 64-bit arithmetic, but which have some targets using a smaller + // pointer width. Examples include aarch64-unknown-linux-gnu_ilp32 and + // x86_64-unknown-linux-gnux32. So our choice of limb width is not + // equivalent to using usize everywhere. + println!("cargo:rustc-cfg=arithmetic64"); + } else { + println!("cargo:rustc-cfg=arithmetic32"); } } diff --git a/src/lexical/large_powers.rs b/src/lexical/large_powers.rs index c63ce1cf2..f96ea79c1 100644 --- a/src/lexical/large_powers.rs +++ b/src/lexical/large_powers.rs @@ -2,8 +2,8 @@ //! Precalculated large powers for limbs. -#[cfg(limb_width_32)] +#[cfg(arithmetic32)] pub(crate) use super::large_powers32::*; -#[cfg(limb_width_64)] +#[cfg(arithmetic64)] pub(crate) use super::large_powers64::*; diff --git a/src/lexical/math.rs b/src/lexical/math.rs index d7122bffa..a8d1d294a 100644 --- a/src/lexical/math.rs +++ b/src/lexical/math.rs @@ -37,29 +37,29 @@ use core::{cmp, iter, mem}; // sparc64 (`UMUL` only supported double-word arguments). // 32-BIT LIMB -#[cfg(limb_width_32)] +#[cfg(arithmetic32)] pub type Limb = u32; -#[cfg(limb_width_32)] +#[cfg(arithmetic32)] pub const POW5_LIMB: &[Limb] = &POW5_32; -#[cfg(limb_width_32)] +#[cfg(arithmetic32)] pub const POW10_LIMB: &[Limb] = &POW10_32; -#[cfg(limb_width_32)] +#[cfg(arithmetic32)] type Wide = u64; // 64-BIT LIMB -#[cfg(limb_width_64)] +#[cfg(arithmetic64)] pub type Limb = u64; -#[cfg(limb_width_64)] +#[cfg(arithmetic64)] pub const POW5_LIMB: &[Limb] = &POW5_64; -#[cfg(limb_width_64)] +#[cfg(arithmetic64)] pub const POW10_LIMB: &[Limb] = &POW10_64; -#[cfg(limb_width_64)] +#[cfg(arithmetic64)] type Wide = u128; /// Cast to limb type. @@ -79,14 +79,14 @@ fn as_wide(t: T) -> Wide { /// Split u64 into limbs, in little-endian order. #[inline] -#[cfg(limb_width_32)] +#[cfg(arithmetic32)] fn split_u64(x: u64) -> [Limb; 2] { [as_limb(x), as_limb(x >> 32)] } /// Split u64 into limbs, in little-endian order. #[inline] -#[cfg(limb_width_64)] +#[cfg(arithmetic64)] fn split_u64(x: u64) -> [Limb; 1] { [as_limb(x)] } diff --git a/src/lexical/mod.rs b/src/lexical/mod.rs index b1a45e218..f5ff13cee 100644 --- a/src/lexical/mod.rs +++ b/src/lexical/mod.rs @@ -28,10 +28,10 @@ pub(crate) mod rounding; mod shift; mod small_powers; -#[cfg(limb_width_32)] +#[cfg(arithmetic32)] mod large_powers32; -#[cfg(limb_width_64)] +#[cfg(arithmetic64)] mod large_powers64; // API diff --git a/src/lexical/small_powers.rs b/src/lexical/small_powers.rs index 219d82611..51d638a13 100644 --- a/src/lexical/small_powers.rs +++ b/src/lexical/small_powers.rs @@ -3,19 +3,19 @@ //! Pre-computed small powers. // 32 BIT -#[cfg(limb_width_32)] +#[cfg(arithmetic32)] pub(crate) const POW5_32: [u32; 14] = [ 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125, ]; -#[cfg(limb_width_32)] +#[cfg(arithmetic32)] pub(crate) const POW10_32: [u32; 10] = [ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, ]; // 64 BIT -#[cfg(limb_width_64)] +#[cfg(arithmetic64)] pub(crate) const POW5_64: [u64; 28] = [ 1, 5, diff --git a/src/read.rs b/src/read.rs index 09e1b41b9..e16b99fdc 100644 --- a/src/read.rs +++ b/src/read.rs @@ -446,20 +446,10 @@ impl<'a> SliceRead<'a> { // benchmarks and it's cross-platform, so probably the right fit. // [1]: https://groups.google.com/forum/#!original/comp.lang.c/2HtQXvg7iKc/xOJeipH6KLMJ - // The following architectures have native support for 64-bit integers, - // but have targets where usize is not 64-bit. - #[cfg(any( - target_arch = "aarch64", - target_arch = "x86_64", - target_arch = "wasm32", - ))] + #[cfg(arithmetic64)] type Chunk = u64; - #[cfg(not(any( - target_arch = "aarch64", - target_arch = "x86_64", - target_arch = "wasm32", - )))] - type Chunk = usize; + #[cfg(arithmetic32)] + type Chunk = u32; const STEP: usize = mem::size_of::(); const ONE_BYTES: Chunk = Chunk::MAX / 255; // 0x0101...01 diff --git a/tests/lexical/math.rs b/tests/lexical/math.rs index 79d3ef3ee..b758339df 100644 --- a/tests/lexical/math.rs +++ b/tests/lexical/math.rs @@ -18,12 +18,12 @@ impl Math for Bigint { } } -#[cfg(limb_width_32)] +#[cfg(arithmetic32)] pub(crate) fn from_u32(x: &[u32]) -> Vec { x.iter().cloned().collect() } -#[cfg(limb_width_64)] +#[cfg(arithmetic64)] pub(crate) fn from_u32(x: &[u32]) -> Vec { let mut v = Vec::::default(); for xi in x.chunks(2) {