From 5fbade740e94191e7a7a6710ef91829937f6582a Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sat, 4 May 2024 12:33:14 -0700 Subject: [PATCH 1/3] Drop the `use_addcarry` build config --- build.rs | 6 ------ src/biguint/addition.rs | 16 +++++----------- src/biguint/subtraction.rs | 16 +++++----------- 3 files changed, 10 insertions(+), 28 deletions(-) diff --git a/build.rs b/build.rs index 4bb21537..8a006815 100644 --- a/build.rs +++ b/build.rs @@ -11,11 +11,5 @@ fn main() { println!("cargo:rustc-cfg=u64_digit"); } - if let Ok(arch) = env::var("CARGO_CFG_TARGET_ARCH") { - if arch == "x86_64" || arch == "x86" { - println!("cargo:rustc-cfg=use_addcarry"); - } - } - println!("cargo:rerun-if-changed=build.rs"); } diff --git a/src/biguint/addition.rs b/src/biguint/addition.rs index 622e1d80..0290669c 100644 --- a/src/biguint/addition.rs +++ b/src/biguint/addition.rs @@ -9,31 +9,25 @@ use core::iter::Sum; use core::ops::{Add, AddAssign}; use num_traits::CheckedAdd; -#[cfg(all(use_addcarry, target_arch = "x86_64"))] -use core::arch::x86_64 as arch; - -#[cfg(all(use_addcarry, target_arch = "x86"))] -use core::arch::x86 as arch; - // Add with carry: -#[cfg(all(use_addcarry, u64_digit))] +#[cfg(target_arch = "x86_64")] #[inline] fn adc(carry: u8, a: u64, b: u64, out: &mut u64) -> u8 { // Safety: There are absolutely no safety concerns with calling `_addcarry_u64`. // It's just unsafe for API consistency with other intrinsics. - unsafe { arch::_addcarry_u64(carry, a, b, out) } + unsafe { core::arch::x86_64::_addcarry_u64(carry, a, b, out) } } -#[cfg(all(use_addcarry, not(u64_digit)))] +#[cfg(target_arch = "x86")] #[inline] fn adc(carry: u8, a: u32, b: u32, out: &mut u32) -> u8 { // Safety: There are absolutely no safety concerns with calling `_addcarry_u32`. // It's just unsafe for API consistency with other intrinsics. - unsafe { arch::_addcarry_u32(carry, a, b, out) } + unsafe { core::arch::x86::_addcarry_u32(carry, a, b, out) } } // fallback for environments where we don't have an addcarry intrinsic -#[cfg(not(use_addcarry))] +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] #[inline] fn adc(carry: u8, a: BigDigit, b: BigDigit, out: &mut BigDigit) -> u8 { use crate::big_digit::DoubleBigDigit; diff --git a/src/biguint/subtraction.rs b/src/biguint/subtraction.rs index 1d2de047..0ed1e0ed 100644 --- a/src/biguint/subtraction.rs +++ b/src/biguint/subtraction.rs @@ -9,31 +9,25 @@ use core::cmp::Ordering::{Equal, Greater, Less}; use core::ops::{Sub, SubAssign}; use num_traits::CheckedSub; -#[cfg(all(use_addcarry, target_arch = "x86_64"))] -use core::arch::x86_64 as arch; - -#[cfg(all(use_addcarry, target_arch = "x86"))] -use core::arch::x86 as arch; - // Subtract with borrow: -#[cfg(all(use_addcarry, u64_digit))] +#[cfg(target_arch = "x86_64")] #[inline] fn sbb(borrow: u8, a: u64, b: u64, out: &mut u64) -> u8 { // Safety: There are absolutely no safety concerns with calling `_subborrow_u64`. // It's just unsafe for API consistency with other intrinsics. - unsafe { arch::_subborrow_u64(borrow, a, b, out) } + unsafe { core::arch::x86_64::_subborrow_u64(borrow, a, b, out) } } -#[cfg(all(use_addcarry, not(u64_digit)))] +#[cfg(target_arch = "x86")] #[inline] fn sbb(borrow: u8, a: u32, b: u32, out: &mut u32) -> u8 { // Safety: There are absolutely no safety concerns with calling `_subborrow_u32`. // It's just unsafe for API consistency with other intrinsics. - unsafe { arch::_subborrow_u32(borrow, a, b, out) } + unsafe { core::arch::x86::_subborrow_u32(borrow, a, b, out) } } // fallback for environments where we don't have a subborrow intrinsic -#[cfg(not(use_addcarry))] +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] #[inline] fn sbb(borrow: u8, a: BigDigit, b: BigDigit, out: &mut BigDigit) -> u8 { use crate::big_digit::SignedDoubleBigDigit; From 49102cbb651fa5b8b66a845c496285d886f1e5c8 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sat, 4 May 2024 12:57:19 -0700 Subject: [PATCH 2/3] Wrap all `cfg(u64_digit)` in macros --- src/bigrand.rs | 68 ++--- src/biguint.rs | 128 +++++----- src/biguint/addition.rs | 122 +++++---- src/biguint/division.rs | 85 ++++--- src/biguint/iter.rs | 457 +++++++++++++++++----------------- src/biguint/multiplication.rs | 72 +++--- src/biguint/serde.rs | 140 +++++------ src/biguint/subtraction.rs | 168 ++++++------- src/lib.rs | 49 ++-- src/macros.rs | 32 +++ 10 files changed, 672 insertions(+), 649 deletions(-) diff --git a/src/bigrand.rs b/src/bigrand.rs index ec032241..0b1cb23c 100644 --- a/src/bigrand.rs +++ b/src/bigrand.rs @@ -47,42 +47,42 @@ fn gen_bits(rng: &mut R, data: &mut [u32], rem: u64) { } impl RandBigInt for R { - #[cfg(not(u64_digit))] - fn gen_biguint(&mut self, bit_size: u64) -> BigUint { - let (digits, rem) = bit_size.div_rem(&32); - let len = (digits + (rem > 0) as u64) - .to_usize() - .expect("capacity overflow"); - let mut data = vec![0u32; len]; - gen_bits(self, &mut data, rem); - biguint_from_vec(data) - } - - #[cfg(u64_digit)] - fn gen_biguint(&mut self, bit_size: u64) -> BigUint { - use core::slice; - - let (digits, rem) = bit_size.div_rem(&32); - let len = (digits + (rem > 0) as u64) - .to_usize() - .expect("capacity overflow"); - let native_digits = Integer::div_ceil(&bit_size, &64); - let native_len = native_digits.to_usize().expect("capacity overflow"); - let mut data = vec![0u64; native_len]; - unsafe { - // Generate bits in a `&mut [u32]` slice for value stability - let ptr = data.as_mut_ptr() as *mut u32; - debug_assert!(native_len * 2 >= len); - let data = slice::from_raw_parts_mut(ptr, len); - gen_bits(self, data, rem); + cfg_digit!( + fn gen_biguint(&mut self, bit_size: u64) -> BigUint { + let (digits, rem) = bit_size.div_rem(&32); + let len = (digits + (rem > 0) as u64) + .to_usize() + .expect("capacity overflow"); + let mut data = vec![0u32; len]; + gen_bits(self, &mut data, rem); + biguint_from_vec(data) } - #[cfg(target_endian = "big")] - for digit in &mut data { - // swap u32 digits into u64 endianness - *digit = (*digit << 32) | (*digit >> 32); + + fn gen_biguint(&mut self, bit_size: u64) -> BigUint { + use core::slice; + + let (digits, rem) = bit_size.div_rem(&32); + let len = (digits + (rem > 0) as u64) + .to_usize() + .expect("capacity overflow"); + let native_digits = Integer::div_ceil(&bit_size, &64); + let native_len = native_digits.to_usize().expect("capacity overflow"); + let mut data = vec![0u64; native_len]; + unsafe { + // Generate bits in a `&mut [u32]` slice for value stability + let ptr = data.as_mut_ptr() as *mut u32; + debug_assert!(native_len * 2 >= len); + let data = slice::from_raw_parts_mut(ptr, len); + gen_bits(self, data, rem); + } + #[cfg(target_endian = "big")] + for digit in &mut data { + // swap u32 digits into u64 endianness + *digit = (*digit << 32) | (*digit >> 32); + } + biguint_from_vec(data) } - biguint_from_vec(data) - } + ); fn gen_bigint(&mut self, bit_size: u64) -> BigInt { loop { diff --git a/src/biguint.rs b/src/biguint.rs index 2ea1de48..9bcd8966 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -542,14 +542,13 @@ impl BigUint { pub fn new(digits: Vec) -> BigUint { let mut big = Self::ZERO; - #[cfg(not(u64_digit))] - { - big.data = digits; - big.normalize(); - } - - #[cfg(u64_digit)] - big.assign_from_slice(&digits); + cfg_digit_expr!( + { + big.data = digits; + big.normalize(); + }, + big.assign_from_slice(&digits) + ); big } @@ -571,11 +570,10 @@ impl BigUint { pub fn assign_from_slice(&mut self, slice: &[u32]) { self.data.clear(); - #[cfg(not(u64_digit))] - self.data.extend_from_slice(slice); - - #[cfg(u64_digit)] - self.data.extend(slice.chunks(2).map(u32_chunk_to_u64)); + cfg_digit_expr!( + self.data.extend_from_slice(slice), + self.data.extend(slice.chunks(2).map(u32_chunk_to_u64)) + ); self.normalize(); } @@ -1118,59 +1116,61 @@ fn u32_chunk_to_u64(chunk: &[u32]) -> u64 { digit } -/// Combine four `u32`s into a single `u128`. -#[cfg(any(test, not(u64_digit)))] -#[inline] -fn u32_to_u128(a: u32, b: u32, c: u32, d: u32) -> u128 { - u128::from(d) | (u128::from(c) << 32) | (u128::from(b) << 64) | (u128::from(a) << 96) -} - -/// Split a single `u128` into four `u32`. -#[cfg(any(test, not(u64_digit)))] -#[inline] -fn u32_from_u128(n: u128) -> (u32, u32, u32, u32) { - ( - (n >> 96) as u32, - (n >> 64) as u32, - (n >> 32) as u32, - n as u32, - ) -} - -#[cfg(not(u64_digit))] -#[test] -fn test_from_slice() { - fn check(slice: &[u32], data: &[BigDigit]) { - assert_eq!(BigUint::from_slice(slice).data, data); - } - check(&[1], &[1]); - check(&[0, 0, 0], &[]); - check(&[1, 2, 0, 0], &[1, 2]); - check(&[0, 0, 1, 2], &[0, 0, 1, 2]); - check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]); - check(&[-1i32 as u32], &[-1i32 as BigDigit]); -} +cfg_32_or_test!( + /// Combine four `u32`s into a single `u128`. + #[inline] + fn u32_to_u128(a: u32, b: u32, c: u32, d: u32) -> u128 { + u128::from(d) | (u128::from(c) << 32) | (u128::from(b) << 64) | (u128::from(a) << 96) + } +); -#[cfg(u64_digit)] -#[test] -fn test_from_slice() { - fn check(slice: &[u32], data: &[BigDigit]) { - assert_eq!( - BigUint::from_slice(slice).data, - data, - "from {:?}, to {:?}", - slice, - data - ); +cfg_32_or_test!( + /// Split a single `u128` into four `u32`. + #[inline] + fn u32_from_u128(n: u128) -> (u32, u32, u32, u32) { + ( + (n >> 96) as u32, + (n >> 64) as u32, + (n >> 32) as u32, + n as u32, + ) } - check(&[1], &[1]); - check(&[0, 0, 0], &[]); - check(&[1, 2], &[8_589_934_593]); - check(&[1, 2, 0, 0], &[8_589_934_593]); - check(&[0, 0, 1, 2], &[0, 8_589_934_593]); - check(&[0, 0, 1, 2, 0, 0], &[0, 8_589_934_593]); - check(&[-1i32 as u32], &[(-1i32 as u32) as BigDigit]); -} +); + +cfg_digit!( + #[test] + fn test_from_slice() { + fn check(slice: &[u32], data: &[BigDigit]) { + assert_eq!(BigUint::from_slice(slice).data, data); + } + check(&[1], &[1]); + check(&[0, 0, 0], &[]); + check(&[1, 2, 0, 0], &[1, 2]); + check(&[0, 0, 1, 2], &[0, 0, 1, 2]); + check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]); + check(&[-1i32 as u32], &[-1i32 as BigDigit]); + } + + #[test] + fn test_from_slice() { + fn check(slice: &[u32], data: &[BigDigit]) { + assert_eq!( + BigUint::from_slice(slice).data, + data, + "from {:?}, to {:?}", + slice, + data + ); + } + check(&[1], &[1]); + check(&[0, 0, 0], &[]); + check(&[1, 2], &[8_589_934_593]); + check(&[1, 2, 0, 0], &[8_589_934_593]); + check(&[0, 0, 1, 2], &[0, 8_589_934_593]); + check(&[0, 0, 1, 2, 0, 0], &[0, 8_589_934_593]); + check(&[-1i32 as u32], &[(-1i32 as u32) as BigDigit]); + } +); #[test] fn test_u32_u128() { diff --git a/src/biguint/addition.rs b/src/biguint/addition.rs index 0290669c..4ad00a8c 100644 --- a/src/biguint/addition.rs +++ b/src/biguint/addition.rs @@ -1,5 +1,3 @@ -#[cfg(not(u64_digit))] -use super::u32_from_u128; use super::{BigUint, IntDigits}; use crate::big_digit::{self, BigDigit}; @@ -148,38 +146,38 @@ impl Add for BigUint { } impl AddAssign for BigUint { - #[cfg(not(u64_digit))] - #[inline] - fn add_assign(&mut self, other: u64) { - let (hi, lo) = big_digit::from_doublebigdigit(other); - if hi == 0 { - *self += lo; - } else { - while self.data.len() < 2 { - self.data.push(0); - } + cfg_digit!( + #[inline] + fn add_assign(&mut self, other: u64) { + let (hi, lo) = big_digit::from_doublebigdigit(other); + if hi == 0 { + *self += lo; + } else { + while self.data.len() < 2 { + self.data.push(0); + } - let carry = __add2(&mut self.data, &[lo, hi]); - if carry != 0 { - self.data.push(carry); + let carry = __add2(&mut self.data, &[lo, hi]); + if carry != 0 { + self.data.push(carry); + } } } - } - #[cfg(u64_digit)] - #[inline] - fn add_assign(&mut self, other: u64) { - if other != 0 { - if self.data.is_empty() { - self.data.push(0); - } + #[inline] + fn add_assign(&mut self, other: u64) { + if other != 0 { + if self.data.is_empty() { + self.data.push(0); + } - let carry = __add2(&mut self.data, &[other as BigDigit]); - if carry != 0 { - self.data.push(carry); + let carry = __add2(&mut self.data, &[other as BigDigit]); + if carry != 0 { + self.data.push(carry); + } } } - } + ); } impl Add for BigUint { @@ -193,49 +191,49 @@ impl Add for BigUint { } impl AddAssign for BigUint { - #[cfg(not(u64_digit))] - #[inline] - fn add_assign(&mut self, other: u128) { - if other <= u128::from(u64::max_value()) { - *self += other as u64 - } else { - let (a, b, c, d) = u32_from_u128(other); - let carry = if a > 0 { - while self.data.len() < 4 { - self.data.push(0); - } - __add2(&mut self.data, &[d, c, b, a]) + cfg_digit!( + #[inline] + fn add_assign(&mut self, other: u128) { + if other <= u128::from(u64::max_value()) { + *self += other as u64 } else { - debug_assert!(b > 0); - while self.data.len() < 3 { - self.data.push(0); + let (a, b, c, d) = super::u32_from_u128(other); + let carry = if a > 0 { + while self.data.len() < 4 { + self.data.push(0); + } + __add2(&mut self.data, &[d, c, b, a]) + } else { + debug_assert!(b > 0); + while self.data.len() < 3 { + self.data.push(0); + } + __add2(&mut self.data, &[d, c, b]) + }; + + if carry != 0 { + self.data.push(carry); } - __add2(&mut self.data, &[d, c, b]) - }; - - if carry != 0 { - self.data.push(carry); } } - } - #[cfg(u64_digit)] - #[inline] - fn add_assign(&mut self, other: u128) { - let (hi, lo) = big_digit::from_doublebigdigit(other); - if hi == 0 { - *self += lo; - } else { - while self.data.len() < 2 { - self.data.push(0); - } + #[inline] + fn add_assign(&mut self, other: u128) { + let (hi, lo) = big_digit::from_doublebigdigit(other); + if hi == 0 { + *self += lo; + } else { + while self.data.len() < 2 { + self.data.push(0); + } - let carry = __add2(&mut self.data, &[lo, hi]); - if carry != 0 { - self.data.push(carry); + let carry = __add2(&mut self.data, &[lo, hi]); + if carry != 0 { + self.data.push(carry); + } } } - } + ); } impl CheckedAdd for BigUint { diff --git a/src/biguint/division.rs b/src/biguint/division.rs index d233c8cb..5706d2db 100644 --- a/src/biguint/division.rs +++ b/src/biguint/division.rs @@ -1,6 +1,4 @@ use super::addition::__add2; -#[cfg(not(u64_digit))] -use super::u32_to_u128; use super::{cmp_slice, BigUint}; use crate::big_digit::{self, BigDigit, DoubleBigDigit}; @@ -386,26 +384,26 @@ impl DivAssign for BigUint { impl Div for u64 { type Output = BigUint; - #[cfg(not(u64_digit))] - #[inline] - fn div(self, other: BigUint) -> BigUint { - match other.data.len() { - 0 => panic!("attempt to divide by zero"), - 1 => From::from(self / u64::from(other.data[0])), - 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])), - _ => BigUint::ZERO, + cfg_digit!( + #[inline] + fn div(self, other: BigUint) -> BigUint { + match other.data.len() { + 0 => panic!("attempt to divide by zero"), + 1 => From::from(self / u64::from(other.data[0])), + 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])), + _ => BigUint::ZERO, + } } - } - #[cfg(u64_digit)] - #[inline] - fn div(self, other: BigUint) -> BigUint { - match other.data.len() { - 0 => panic!("attempt to divide by zero"), - 1 => From::from(self / other.data[0]), - _ => BigUint::ZERO, + #[inline] + fn div(self, other: BigUint) -> BigUint { + match other.data.len() { + 0 => panic!("attempt to divide by zero"), + 1 => From::from(self / other.data[0]), + _ => BigUint::ZERO, + } } - } + ); } impl Div for BigUint { @@ -428,33 +426,34 @@ impl DivAssign for BigUint { impl Div for u128 { type Output = BigUint; - #[cfg(not(u64_digit))] - #[inline] - fn div(self, other: BigUint) -> BigUint { - match other.data.len() { - 0 => panic!("attempt to divide by zero"), - 1 => From::from(self / u128::from(other.data[0])), - 2 => From::from( - self / u128::from(big_digit::to_doublebigdigit(other.data[1], other.data[0])), - ), - 3 => From::from(self / u32_to_u128(0, other.data[2], other.data[1], other.data[0])), - 4 => From::from( - self / u32_to_u128(other.data[3], other.data[2], other.data[1], other.data[0]), - ), - _ => BigUint::ZERO, + cfg_digit!( + #[inline] + fn div(self, other: BigUint) -> BigUint { + use super::u32_to_u128; + match other.data.len() { + 0 => panic!("attempt to divide by zero"), + 1 => From::from(self / u128::from(other.data[0])), + 2 => From::from( + self / u128::from(big_digit::to_doublebigdigit(other.data[1], other.data[0])), + ), + 3 => From::from(self / u32_to_u128(0, other.data[2], other.data[1], other.data[0])), + 4 => From::from( + self / u32_to_u128(other.data[3], other.data[2], other.data[1], other.data[0]), + ), + _ => BigUint::ZERO, + } } - } - #[cfg(u64_digit)] - #[inline] - fn div(self, other: BigUint) -> BigUint { - match other.data.len() { - 0 => panic!("attempt to divide by zero"), - 1 => From::from(self / other.data[0] as u128), - 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])), - _ => BigUint::ZERO, + #[inline] + fn div(self, other: BigUint) -> BigUint { + match other.data.len() { + 0 => panic!("attempt to divide by zero"), + 1 => From::from(self / other.data[0] as u128), + 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])), + _ => BigUint::ZERO, + } } - } + ); } forward_val_ref_binop!(impl Rem for BigUint, rem); diff --git a/src/biguint/iter.rs b/src/biguint/iter.rs index 1bb701be..066c9c1e 100644 --- a/src/biguint/iter.rs +++ b/src/biguint/iter.rs @@ -1,268 +1,271 @@ use core::iter::FusedIterator; -#[cfg(not(u64_digit))] -use super::u32_chunk_to_u64; - -/// An iterator of `u32` digits representation of a `BigUint` or `BigInt`, -/// ordered least significant digit first. -pub struct U32Digits<'a> { - #[cfg(u64_digit)] - data: &'a [u64], - #[cfg(u64_digit)] - next_is_lo: bool, - #[cfg(u64_digit)] - last_hi_is_zero: bool, - - #[cfg(not(u64_digit))] - it: core::slice::Iter<'a, u32>, -} - -#[cfg(u64_digit)] -impl<'a> U32Digits<'a> { - #[inline] - pub(super) fn new(data: &'a [u64]) -> Self { - let last_hi_is_zero = data - .last() - .map(|&last| { - let last_hi = (last >> 32) as u32; - last_hi == 0 - }) - .unwrap_or(false); - U32Digits { - data, - next_is_lo: true, - last_hi_is_zero, - } +cfg_digit!( + /// An iterator of `u32` digits representation of a `BigUint` or `BigInt`, + /// ordered least significant digit first. + pub struct U32Digits<'a> { + it: core::slice::Iter<'a, u32>, } -} -#[cfg(u64_digit)] -impl Iterator for U32Digits<'_> { - type Item = u32; - #[inline] - fn next(&mut self) -> Option { - match self.data.split_first() { - Some((&first, data)) => { - let next_is_lo = self.next_is_lo; - self.next_is_lo = !next_is_lo; - if next_is_lo { - Some(first as u32) - } else { - self.data = data; - if data.is_empty() && self.last_hi_is_zero { - self.last_hi_is_zero = false; - None - } else { - Some((first >> 32) as u32) - } - } + /// An iterator of `u32` digits representation of a `BigUint` or `BigInt`, + /// ordered least significant digit first. + pub struct U32Digits<'a> { + data: &'a [u64], + next_is_lo: bool, + last_hi_is_zero: bool, + } +); + +cfg_digit!( + const _: () = { + impl<'a> U32Digits<'a> { + #[inline] + pub(super) fn new(data: &'a [u32]) -> Self { + Self { it: data.iter() } } - None => None, } - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - let len = self.len(); - (len, Some(len)) - } + impl Iterator for U32Digits<'_> { + type Item = u32; + #[inline] + fn next(&mut self) -> Option { + self.it.next().cloned() + } - #[inline] - fn last(self) -> Option { - self.data.last().map(|&last| { - if self.last_hi_is_zero { - last as u32 - } else { - (last >> 32) as u32 + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() } - }) - } - #[inline] - fn count(self) -> usize { - self.len() - } -} + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.it.nth(n).cloned() + } -#[cfg(u64_digit)] -impl DoubleEndedIterator for U32Digits<'_> { - fn next_back(&mut self) -> Option { - match self.data.split_last() { - Some((&last, data)) => { - let last_is_lo = self.last_hi_is_zero; - self.last_hi_is_zero = !last_is_lo; - if last_is_lo { - self.data = data; - if data.is_empty() && !self.next_is_lo { - self.next_is_lo = true; - None - } else { - Some(last as u32) - } - } else { - Some((last >> 32) as u32) - } + #[inline] + fn last(self) -> Option { + self.it.last().cloned() } - None => None, - } - } -} -#[cfg(u64_digit)] -impl ExactSizeIterator for U32Digits<'_> { - #[inline] - fn len(&self) -> usize { - self.data.len() * 2 - usize::from(self.last_hi_is_zero) - usize::from(!self.next_is_lo) - } -} + #[inline] + fn count(self) -> usize { + self.it.count() + } + } -#[cfg(not(u64_digit))] -impl<'a> U32Digits<'a> { - #[inline] - pub(super) fn new(data: &'a [u32]) -> Self { - Self { it: data.iter() } - } -} + impl DoubleEndedIterator for U32Digits<'_> { + fn next_back(&mut self) -> Option { + self.it.next_back().cloned() + } + } -#[cfg(not(u64_digit))] -impl Iterator for U32Digits<'_> { - type Item = u32; - #[inline] - fn next(&mut self) -> Option { - self.it.next().cloned() - } + impl ExactSizeIterator for U32Digits<'_> { + #[inline] + fn len(&self) -> usize { + self.it.len() + } + } + }; + + const _: () = { + impl<'a> U32Digits<'a> { + #[inline] + pub(super) fn new(data: &'a [u64]) -> Self { + let last_hi_is_zero = data + .last() + .map(|&last| { + let last_hi = (last >> 32) as u32; + last_hi == 0 + }) + .unwrap_or(false); + U32Digits { + data, + next_is_lo: true, + last_hi_is_zero, + } + } + } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.it.size_hint() - } + impl Iterator for U32Digits<'_> { + type Item = u32; + #[inline] + fn next(&mut self) -> Option { + match self.data.split_first() { + Some((&first, data)) => { + let next_is_lo = self.next_is_lo; + self.next_is_lo = !next_is_lo; + if next_is_lo { + Some(first as u32) + } else { + self.data = data; + if data.is_empty() && self.last_hi_is_zero { + self.last_hi_is_zero = false; + None + } else { + Some((first >> 32) as u32) + } + } + } + None => None, + } + } - #[inline] - fn nth(&mut self, n: usize) -> Option { - self.it.nth(n).cloned() - } + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } - #[inline] - fn last(self) -> Option { - self.it.last().cloned() - } + #[inline] + fn last(self) -> Option { + self.data.last().map(|&last| { + if self.last_hi_is_zero { + last as u32 + } else { + (last >> 32) as u32 + } + }) + } - #[inline] - fn count(self) -> usize { - self.it.count() - } -} + #[inline] + fn count(self) -> usize { + self.len() + } + } -#[cfg(not(u64_digit))] -impl DoubleEndedIterator for U32Digits<'_> { - fn next_back(&mut self) -> Option { - self.it.next_back().cloned() - } -} + impl DoubleEndedIterator for U32Digits<'_> { + fn next_back(&mut self) -> Option { + match self.data.split_last() { + Some((&last, data)) => { + let last_is_lo = self.last_hi_is_zero; + self.last_hi_is_zero = !last_is_lo; + if last_is_lo { + self.data = data; + if data.is_empty() && !self.next_is_lo { + self.next_is_lo = true; + None + } else { + Some(last as u32) + } + } else { + Some((last >> 32) as u32) + } + } + None => None, + } + } + } -#[cfg(not(u64_digit))] -impl ExactSizeIterator for U32Digits<'_> { - #[inline] - fn len(&self) -> usize { - self.it.len() - } -} + impl ExactSizeIterator for U32Digits<'_> { + #[inline] + fn len(&self) -> usize { + self.data.len() * 2 + - usize::from(self.last_hi_is_zero) + - usize::from(!self.next_is_lo) + } + } + }; +); impl FusedIterator for U32Digits<'_> {} -/// An iterator of `u64` digits representation of a `BigUint` or `BigInt`, -/// ordered least significant digit first. -pub struct U64Digits<'a> { - #[cfg(not(u64_digit))] - it: core::slice::Chunks<'a, u32>, - - #[cfg(u64_digit)] - it: core::slice::Iter<'a, u64>, -} - -#[cfg(not(u64_digit))] -impl<'a> U64Digits<'a> { - #[inline] - pub(super) fn new(data: &'a [u32]) -> Self { - U64Digits { it: data.chunks(2) } +cfg_digit!( + /// An iterator of `u64` digits representation of a `BigUint` or `BigInt`, + /// ordered least significant digit first. + pub struct U64Digits<'a> { + it: core::slice::Chunks<'a, u32>, } -} -#[cfg(not(u64_digit))] -impl Iterator for U64Digits<'_> { - type Item = u64; - #[inline] - fn next(&mut self) -> Option { - self.it.next().map(u32_chunk_to_u64) + /// An iterator of `u64` digits representation of a `BigUint` or `BigInt`, + /// ordered least significant digit first. + pub struct U64Digits<'a> { + it: core::slice::Iter<'a, u64>, } +); + +cfg_digit!( + const _: () = { + impl<'a> U64Digits<'a> { + #[inline] + pub(super) fn new(data: &'a [u32]) -> Self { + U64Digits { it: data.chunks(2) } + } + } - #[inline] - fn size_hint(&self) -> (usize, Option) { - let len = self.len(); - (len, Some(len)) - } + impl Iterator for U64Digits<'_> { + type Item = u64; + #[inline] + fn next(&mut self) -> Option { + self.it.next().map(super::u32_chunk_to_u64) + } - #[inline] - fn last(self) -> Option { - self.it.last().map(u32_chunk_to_u64) - } + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } - #[inline] - fn count(self) -> usize { - self.len() - } -} + #[inline] + fn last(self) -> Option { + self.it.last().map(super::u32_chunk_to_u64) + } -#[cfg(not(u64_digit))] -impl DoubleEndedIterator for U64Digits<'_> { - fn next_back(&mut self) -> Option { - self.it.next_back().map(u32_chunk_to_u64) - } -} + #[inline] + fn count(self) -> usize { + self.len() + } + } -#[cfg(u64_digit)] -impl<'a> U64Digits<'a> { - #[inline] - pub(super) fn new(data: &'a [u64]) -> Self { - Self { it: data.iter() } - } -} + impl DoubleEndedIterator for U64Digits<'_> { + fn next_back(&mut self) -> Option { + self.it.next_back().map(super::u32_chunk_to_u64) + } + } + }; -#[cfg(u64_digit)] -impl Iterator for U64Digits<'_> { - type Item = u64; - #[inline] - fn next(&mut self) -> Option { - self.it.next().cloned() - } + const _: () = { + impl<'a> U64Digits<'a> { + #[inline] + pub(super) fn new(data: &'a [u64]) -> Self { + Self { it: data.iter() } + } + } - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.it.size_hint() - } + impl Iterator for U64Digits<'_> { + type Item = u64; + #[inline] + fn next(&mut self) -> Option { + self.it.next().cloned() + } - #[inline] - fn nth(&mut self, n: usize) -> Option { - self.it.nth(n).cloned() - } + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } - #[inline] - fn last(self) -> Option { - self.it.last().cloned() - } + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.it.nth(n).cloned() + } - #[inline] - fn count(self) -> usize { - self.it.count() - } -} + #[inline] + fn last(self) -> Option { + self.it.last().cloned() + } -#[cfg(u64_digit)] -impl DoubleEndedIterator for U64Digits<'_> { - fn next_back(&mut self) -> Option { - self.it.next_back().cloned() - } -} + #[inline] + fn count(self) -> usize { + self.it.count() + } + } + + impl DoubleEndedIterator for U64Digits<'_> { + fn next_back(&mut self) -> Option { + self.it.next_back().cloned() + } + } + }; +); impl ExactSizeIterator for U64Digits<'_> { #[inline] diff --git a/src/biguint/multiplication.rs b/src/biguint/multiplication.rs index c2f547d6..c97c7e1a 100644 --- a/src/biguint/multiplication.rs +++ b/src/biguint/multiplication.rs @@ -1,7 +1,5 @@ use super::addition::{__add2, add2}; use super::subtraction::sub2; -#[cfg(not(u64_digit))] -use super::u32_from_u128; use super::{biguint_from_vec, cmp_slice, BigUint, IntDigits}; use crate::big_digit::{self, BigDigit, DoubleBigDigit}; @@ -544,22 +542,22 @@ impl Mul for BigUint { } } impl MulAssign for BigUint { - #[cfg(not(u64_digit))] - #[inline] - fn mul_assign(&mut self, other: u64) { - if let Some(other) = BigDigit::from_u64(other) { - scalar_mul(self, other); - } else { - let (hi, lo) = big_digit::from_doublebigdigit(other); - *self = mul3(&self.data, &[lo, hi]); + cfg_digit!( + #[inline] + fn mul_assign(&mut self, other: u64) { + if let Some(other) = BigDigit::from_u64(other) { + scalar_mul(self, other); + } else { + let (hi, lo) = big_digit::from_doublebigdigit(other); + *self = mul3(&self.data, &[lo, hi]); + } } - } - #[cfg(u64_digit)] - #[inline] - fn mul_assign(&mut self, other: u64) { - scalar_mul(self, other); - } + #[inline] + fn mul_assign(&mut self, other: u64) { + scalar_mul(self, other); + } + ); } impl Mul for BigUint { @@ -573,30 +571,30 @@ impl Mul for BigUint { } impl MulAssign for BigUint { - #[cfg(not(u64_digit))] - #[inline] - fn mul_assign(&mut self, other: u128) { - if let Some(other) = BigDigit::from_u128(other) { - scalar_mul(self, other); - } else { - *self = match u32_from_u128(other) { - (0, 0, c, d) => mul3(&self.data, &[d, c]), - (0, b, c, d) => mul3(&self.data, &[d, c, b]), - (a, b, c, d) => mul3(&self.data, &[d, c, b, a]), - }; + cfg_digit!( + #[inline] + fn mul_assign(&mut self, other: u128) { + if let Some(other) = BigDigit::from_u128(other) { + scalar_mul(self, other); + } else { + *self = match super::u32_from_u128(other) { + (0, 0, c, d) => mul3(&self.data, &[d, c]), + (0, b, c, d) => mul3(&self.data, &[d, c, b]), + (a, b, c, d) => mul3(&self.data, &[d, c, b, a]), + }; + } } - } - #[cfg(u64_digit)] - #[inline] - fn mul_assign(&mut self, other: u128) { - if let Some(other) = BigDigit::from_u128(other) { - scalar_mul(self, other); - } else { - let (hi, lo) = big_digit::from_doublebigdigit(other); - *self = mul3(&self.data, &[lo, hi]); + #[inline] + fn mul_assign(&mut self, other: u128) { + if let Some(other) = BigDigit::from_u128(other) { + scalar_mul(self, other); + } else { + let (hi, lo) = big_digit::from_doublebigdigit(other); + *self = mul3(&self.data, &[lo, hi]); + } } - } + ); } impl CheckedMul for BigUint { diff --git a/src/biguint/serde.rs b/src/biguint/serde.rs index 3240f093..1fadf16a 100644 --- a/src/biguint/serde.rs +++ b/src/biguint/serde.rs @@ -18,44 +18,44 @@ fn cautious(hint: Option) -> usize { } impl Serialize for BigUint { - #[cfg(not(u64_digit))] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - // Note: do not change the serialization format, or it may break forward - // and backward compatibility of serialized data! If we ever change the - // internal representation, we should still serialize in base-`u32`. - let data: &[u32] = &self.data; - data.serialize(serializer) - } + cfg_digit!( + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // Note: do not change the serialization format, or it may break forward + // and backward compatibility of serialized data! If we ever change the + // internal representation, we should still serialize in base-`u32`. + let data: &[u32] = &self.data; + data.serialize(serializer) + } - #[cfg(u64_digit)] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - use serde::ser::SerializeSeq; - - if let Some((&last, data)) = self.data.split_last() { - let last_lo = last as u32; - let last_hi = (last >> 32) as u32; - let u32_len = data.len() * 2 + 1 + (last_hi != 0) as usize; - let mut seq = serializer.serialize_seq(Some(u32_len))?; - for &x in data { - seq.serialize_element(&(x as u32))?; - seq.serialize_element(&((x >> 32) as u32))?; - } - seq.serialize_element(&last_lo)?; - if last_hi != 0 { - seq.serialize_element(&last_hi)?; + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + use serde::ser::SerializeSeq; + + if let Some((&last, data)) = self.data.split_last() { + let last_lo = last as u32; + let last_hi = (last >> 32) as u32; + let u32_len = data.len() * 2 + 1 + (last_hi != 0) as usize; + let mut seq = serializer.serialize_seq(Some(u32_len))?; + for &x in data { + seq.serialize_element(&(x as u32))?; + seq.serialize_element(&((x >> 32) as u32))?; + } + seq.serialize_element(&last_lo)?; + if last_hi != 0 { + seq.serialize_element(&last_hi)?; + } + seq.end() + } else { + let data: &[u32] = &[]; + data.serialize(serializer) } - seq.end() - } else { - let data: &[u32] = &[]; - data.serialize(serializer) } - } + ); } impl<'de> Deserialize<'de> for BigUint { @@ -76,44 +76,44 @@ impl<'de> Visitor<'de> for U32Visitor { formatter.write_str("a sequence of unsigned 32-bit numbers") } - #[cfg(not(u64_digit))] - fn visit_seq(self, mut seq: S) -> Result - where - S: SeqAccess<'de>, - { - let len = cautious(seq.size_hint()); - let mut data = Vec::with_capacity(len); - - while let Some(value) = seq.next_element::()? { - data.push(value); - } - - Ok(biguint_from_vec(data)) - } - - #[cfg(u64_digit)] - fn visit_seq(self, mut seq: S) -> Result - where - S: SeqAccess<'de>, - { - use crate::big_digit::BigDigit; - use num_integer::Integer; - - let u32_len = cautious(seq.size_hint()); - let len = Integer::div_ceil(&u32_len, &2); - let mut data = Vec::with_capacity(len); + cfg_digit!( + fn visit_seq(self, mut seq: S) -> Result + where + S: SeqAccess<'de>, + { + let len = cautious(seq.size_hint()); + let mut data = Vec::with_capacity(len); - while let Some(lo) = seq.next_element::()? { - let mut value = BigDigit::from(lo); - if let Some(hi) = seq.next_element::()? { - value |= BigDigit::from(hi) << 32; + while let Some(value) = seq.next_element::()? { data.push(value); - } else { - data.push(value); - break; } + + Ok(biguint_from_vec(data)) } - Ok(biguint_from_vec(data)) - } + fn visit_seq(self, mut seq: S) -> Result + where + S: SeqAccess<'de>, + { + use crate::big_digit::BigDigit; + use num_integer::Integer; + + let u32_len = cautious(seq.size_hint()); + let len = Integer::div_ceil(&u32_len, &2); + let mut data = Vec::with_capacity(len); + + while let Some(lo) = seq.next_element::()? { + let mut value = BigDigit::from(lo); + if let Some(hi) = seq.next_element::()? { + value |= BigDigit::from(hi) << 32; + data.push(value); + } else { + data.push(value); + break; + } + } + + Ok(biguint_from_vec(data)) + } + ); } diff --git a/src/biguint/subtraction.rs b/src/biguint/subtraction.rs index 0ed1e0ed..58839403 100644 --- a/src/biguint/subtraction.rs +++ b/src/biguint/subtraction.rs @@ -1,5 +1,3 @@ -#[cfg(not(u64_digit))] -use super::u32_from_u128; use super::BigUint; use crate::big_digit::{self, BigDigit}; @@ -161,27 +159,27 @@ impl SubAssign for BigUint { impl Sub for u32 { type Output = BigUint; - #[cfg(not(u64_digit))] - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - if other.data.len() == 0 { - other.data.push(self); - } else { - sub2rev(&[self], &mut other.data[..]); + cfg_digit!( + #[inline] + fn sub(self, mut other: BigUint) -> BigUint { + if other.data.len() == 0 { + other.data.push(self); + } else { + sub2rev(&[self], &mut other.data[..]); + } + other.normalized() } - other.normalized() - } - #[cfg(u64_digit)] - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - if other.data.is_empty() { - other.data.push(self as BigDigit); - } else { - sub2rev(&[self as BigDigit], &mut other.data[..]); + #[inline] + fn sub(self, mut other: BigUint) -> BigUint { + if other.data.is_empty() { + other.data.push(self as BigDigit); + } else { + sub2rev(&[self as BigDigit], &mut other.data[..]); + } + other.normalized() } - other.normalized() - } + ); } impl Sub for BigUint { @@ -195,47 +193,47 @@ impl Sub for BigUint { } impl SubAssign for BigUint { - #[cfg(not(u64_digit))] - #[inline] - fn sub_assign(&mut self, other: u64) { - let (hi, lo) = big_digit::from_doublebigdigit(other); - sub2(&mut self.data[..], &[lo, hi]); - self.normalize(); - } + cfg_digit!( + #[inline] + fn sub_assign(&mut self, other: u64) { + let (hi, lo) = big_digit::from_doublebigdigit(other); + sub2(&mut self.data[..], &[lo, hi]); + self.normalize(); + } - #[cfg(u64_digit)] - #[inline] - fn sub_assign(&mut self, other: u64) { - sub2(&mut self.data[..], &[other as BigDigit]); - self.normalize(); - } + #[inline] + fn sub_assign(&mut self, other: u64) { + sub2(&mut self.data[..], &[other as BigDigit]); + self.normalize(); + } + ); } impl Sub for u64 { type Output = BigUint; - #[cfg(not(u64_digit))] - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - while other.data.len() < 2 { - other.data.push(0); - } + cfg_digit!( + #[inline] + fn sub(self, mut other: BigUint) -> BigUint { + while other.data.len() < 2 { + other.data.push(0); + } - let (hi, lo) = big_digit::from_doublebigdigit(self); - sub2rev(&[lo, hi], &mut other.data[..]); - other.normalized() - } + let (hi, lo) = big_digit::from_doublebigdigit(self); + sub2rev(&[lo, hi], &mut other.data[..]); + other.normalized() + } - #[cfg(u64_digit)] - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - if other.data.is_empty() { - other.data.push(self); - } else { - sub2rev(&[self], &mut other.data[..]); + #[inline] + fn sub(self, mut other: BigUint) -> BigUint { + if other.data.is_empty() { + other.data.push(self); + } else { + sub2rev(&[self], &mut other.data[..]); + } + other.normalized() } - other.normalized() - } + ); } impl Sub for BigUint { @@ -249,49 +247,49 @@ impl Sub for BigUint { } impl SubAssign for BigUint { - #[cfg(not(u64_digit))] - #[inline] - fn sub_assign(&mut self, other: u128) { - let (a, b, c, d) = u32_from_u128(other); - sub2(&mut self.data[..], &[d, c, b, a]); - self.normalize(); - } + cfg_digit!( + #[inline] + fn sub_assign(&mut self, other: u128) { + let (a, b, c, d) = super::u32_from_u128(other); + sub2(&mut self.data[..], &[d, c, b, a]); + self.normalize(); + } - #[cfg(u64_digit)] - #[inline] - fn sub_assign(&mut self, other: u128) { - let (hi, lo) = big_digit::from_doublebigdigit(other); - sub2(&mut self.data[..], &[lo, hi]); - self.normalize(); - } + #[inline] + fn sub_assign(&mut self, other: u128) { + let (hi, lo) = big_digit::from_doublebigdigit(other); + sub2(&mut self.data[..], &[lo, hi]); + self.normalize(); + } + ); } impl Sub for u128 { type Output = BigUint; - #[cfg(not(u64_digit))] - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - while other.data.len() < 4 { - other.data.push(0); + cfg_digit!( + #[inline] + fn sub(self, mut other: BigUint) -> BigUint { + while other.data.len() < 4 { + other.data.push(0); + } + + let (a, b, c, d) = super::u32_from_u128(self); + sub2rev(&[d, c, b, a], &mut other.data[..]); + other.normalized() } - let (a, b, c, d) = u32_from_u128(self); - sub2rev(&[d, c, b, a], &mut other.data[..]); - other.normalized() - } + #[inline] + fn sub(self, mut other: BigUint) -> BigUint { + while other.data.len() < 2 { + other.data.push(0); + } - #[cfg(u64_digit)] - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - while other.data.len() < 2 { - other.data.push(0); + let (hi, lo) = big_digit::from_doublebigdigit(self); + sub2rev(&[lo, hi], &mut other.data[..]); + other.normalized() } - - let (hi, lo) = big_digit::from_doublebigdigit(self); - sub2rev(&[lo, hi], &mut other.data[..]); - other.normalized() - } + ); } impl CheckedSub for BigUint { diff --git a/src/lib.rs b/src/lib.rs index ea7bd95c..b807fd20 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -233,36 +233,31 @@ pub use crate::bigint::ToBigInt; pub use crate::bigrand::{RandBigInt, RandomBits, UniformBigInt, UniformBigUint}; mod big_digit { - /// A [`BigDigit`] is a [`BigUint`]'s composing element. - #[cfg(not(u64_digit))] - pub(crate) type BigDigit = u32; - #[cfg(u64_digit)] - pub(crate) type BigDigit = u64; - - /// A [`DoubleBigDigit`] is the internal type used to do the computations. Its - /// size is the double of the size of [`BigDigit`]. - #[cfg(not(u64_digit))] - pub(crate) type DoubleBigDigit = u64; - #[cfg(u64_digit)] - pub(crate) type DoubleBigDigit = u128; - - /// A [`SignedDoubleBigDigit`] is the signed version of [`DoubleBigDigit`]. - #[cfg(not(u64_digit))] - pub(crate) type SignedDoubleBigDigit = i64; - #[cfg(u64_digit)] - pub(crate) type SignedDoubleBigDigit = i128; - - // [`DoubleBigDigit`] size dependent - #[cfg(not(u64_digit))] - pub(crate) const BITS: u8 = 32; - #[cfg(u64_digit)] - pub(crate) const BITS: u8 = 64; - + // A [`BigDigit`] is a [`BigUint`]'s composing element. + cfg_digit!( + pub(crate) type BigDigit = u32; + pub(crate) type BigDigit = u64; + ); + + // A [`DoubleBigDigit`] is the internal type used to do the computations. Its + // size is the double of the size of [`BigDigit`]. + cfg_digit!( + pub(crate) type DoubleBigDigit = u64; + pub(crate) type DoubleBigDigit = u128; + ); + + // A [`SignedDoubleBigDigit`] is the signed version of [`DoubleBigDigit`]. + cfg_digit!( + pub(crate) type SignedDoubleBigDigit = i64; + pub(crate) type SignedDoubleBigDigit = i128; + ); + + pub(crate) const BITS: u8 = BigDigit::BITS as u8; pub(crate) const HALF_BITS: u8 = BITS / 2; pub(crate) const HALF: BigDigit = (1 << HALF_BITS) - 1; - const LO_MASK: DoubleBigDigit = (1 << BITS) - 1; - pub(crate) const MAX: BigDigit = LO_MASK as BigDigit; + pub(crate) const MAX: BigDigit = BigDigit::MAX; + const LO_MASK: DoubleBigDigit = MAX as DoubleBigDigit; #[inline] fn get_hi(n: DoubleBigDigit) -> BigDigit { diff --git a/src/macros.rs b/src/macros.rs index 8977f217..dda449f7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,5 +1,37 @@ #![allow(unused_macros)] +macro_rules! cfg_32 { + ($($any:tt)+) => { + #[cfg(not(u64_digit))] $($any)+ + } +} + +macro_rules! cfg_32_or_test { + ($($any:tt)+) => { + #[cfg(any(not(u64_digit), test))] $($any)+ + } +} + +macro_rules! cfg_64 { + ($($any:tt)+) => { + #[cfg(u64_digit)] $($any)+ + } +} + +macro_rules! cfg_digit { + ($item32:item $item64:item) => { + cfg_32!($item32); + cfg_64!($item64); + }; +} + +macro_rules! cfg_digit_expr { + ($expr32:expr, $expr64:expr) => { + cfg_32!($expr32); + cfg_64!($expr64); + }; +} + macro_rules! forward_val_val_binop { (impl $imp:ident for $res:ty, $method:ident) => { impl $imp<$res> for $res { From 9eab65d99061cb1d7586a536482f205a4cea9e84 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sat, 4 May 2024 13:04:08 -0700 Subject: [PATCH 3/3] Move the `u64_digit` build config into the macros --- Cargo.toml | 1 - build.rs | 15 --------------- src/macros.rs | 6 +++--- 3 files changed, 3 insertions(+), 19 deletions(-) delete mode 100644 build.rs diff --git a/Cargo.toml b/Cargo.toml index a3bdcea3..e63feed9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,6 @@ name = "num-bigint" repository = "https://github.com/rust-num/num-bigint" version = "0.4.4" readme = "README.md" -build = "build.rs" exclude = ["/ci/*", "/.github/*"] edition = "2021" rust-version = "1.60" diff --git a/build.rs b/build.rs deleted file mode 100644 index 8a006815..00000000 --- a/build.rs +++ /dev/null @@ -1,15 +0,0 @@ -use std::env; - -fn main() { - let ptr_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH"); - let u64_digit = ptr_width - .as_ref() - .map(|x| x == "64" || x == "128") - .unwrap_or(false); - - if u64_digit { - println!("cargo:rustc-cfg=u64_digit"); - } - - println!("cargo:rerun-if-changed=build.rs"); -} diff --git a/src/macros.rs b/src/macros.rs index dda449f7..ab821907 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -2,19 +2,19 @@ macro_rules! cfg_32 { ($($any:tt)+) => { - #[cfg(not(u64_digit))] $($any)+ + #[cfg(not(any(target_pointer_width = "64", target_pointer_width = "128")))] $($any)+ } } macro_rules! cfg_32_or_test { ($($any:tt)+) => { - #[cfg(any(not(u64_digit), test))] $($any)+ + #[cfg(any(not(any(target_pointer_width = "64", target_pointer_width = "128")), test))] $($any)+ } } macro_rules! cfg_64 { ($($any:tt)+) => { - #[cfg(u64_digit)] $($any)+ + #[cfg(any(target_pointer_width = "64", target_pointer_width = "128"))] $($any)+ } }