num: Separate public API from internal implementations

Currently we have a single `core::num` module that contains both thin
wrapper API and higher-complexity numeric routines. Restructure this by
moving implementation details to a new `imp` module.

This results in a more clean separation of what is actually user-facing
compared to items that have a stability attribute because they are
public for testing.
This commit is contained in:
Trevor Gross
2026-01-31 03:43:21 -06:00
parent 7057231bd7
commit 23e44f65aa
54 changed files with 193 additions and 169 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
use crate::fmt::{Debug, Display, Formatter, LowerExp, Result, UpperExp};
use crate::mem::MaybeUninit;
use crate::num::{flt2dec, fmt as numfmt};
use crate::num::imp::{flt2dec, fmt as numfmt};
#[doc(hidden)]
trait GeneralFormat: PartialOrd {
+1 -1
View File
@@ -6,7 +6,7 @@
use crate::char::EscapeDebugExtArgs;
use crate::hint::assert_unchecked;
use crate::marker::{PhantomData, PointeeSized};
use crate::num::fmt as numfmt;
use crate::num::imp::fmt as numfmt;
use crate::ops::Deref;
use crate::ptr::NonNull;
use crate::{iter, mem, result, str};
+1 -1
View File
@@ -2,7 +2,7 @@
use crate::fmt::NumBuffer;
use crate::mem::MaybeUninit;
use crate::num::fmt as numfmt;
use crate::num::imp::fmt as numfmt;
use crate::{fmt, str};
/// Formatting of integers with a non-decimal radix.
+1 -1
View File
@@ -14,7 +14,7 @@
use crate::convert::FloatToInt;
use crate::num::FpCategory;
#[cfg(not(test))]
use crate::num::libm;
use crate::num::imp::libm;
use crate::panic::const_assert;
use crate::{intrinsics, mem};
+1 -1
View File
@@ -1633,7 +1633,7 @@ pub const fn algebraic_rem(self, rhs: f32) -> f32 {
#[unstable(feature = "core_float_math", issue = "137578")]
pub mod math {
use crate::intrinsics;
use crate::num::libm;
use crate::num::imp::libm;
/// Experimental version of `floor` in `core`. See [`f32::floor`] for details.
///
+1 -1
View File
@@ -1631,7 +1631,7 @@ pub const fn algebraic_rem(self, rhs: f64) -> f64 {
/// They will be stabilized as inherent methods._
pub mod math {
use crate::intrinsics;
use crate::num::libm;
use crate::num::imp::libm;
/// Experimental version of `floor` in `core`. See [`f64::floor`] for details.
///
@@ -251,7 +251,7 @@ pub fn mul_pow2(&mut self, bits: usize) -> &mut $name {
/// Multiplies itself by `5^e` and returns its own mutable reference.
pub fn mul_pow5(&mut self, mut e: usize) -> &mut $name {
use crate::num::bignum::SMALL_POW5;
use crate::num::imp::bignum::SMALL_POW5;
// There are exactly n trailing zeros on 2^n, and the only relevant digit sizes
// are consecutive powers of two, so this is well suited index for the table.
@@ -281,7 +281,7 @@ pub fn mul_pow5(&mut self, mut e: usize) -> &mut $name {
pub fn mul_digits<'a>(&'a mut self, other: &[$ty]) -> &'a mut $name {
// the internal routine. works best when aa.len() <= bb.len().
fn mul_inner(ret: &mut [$ty; $n], aa: &[$ty], bb: &[$ty]) -> usize {
use crate::num::bignum::FullOps;
use crate::num::imp::bignum::FullOps;
let mut retsz = 0;
for (i, &a) in aa.iter().enumerate() {
@@ -320,7 +320,7 @@ pub fn mul_digits<'a>(&'a mut self, other: &[$ty]) -> &'a mut $name {
/// Divides itself by a digit-sized `other` and returns its own
/// mutable reference *and* the remainder.
pub fn div_rem_small(&mut self, other: $ty) -> (&mut $name, $ty) {
use crate::num::bignum::FullOps;
use crate::num::imp::bignum::FullOps;
assert!(other > 0);
@@ -1,7 +1,9 @@
//! Representation of a float as the significant digits and exponent.
use crate::num::dec2flt::float::RawFloat;
use crate::num::dec2flt::fpu::set_precision;
use dec2flt::float::RawFloat;
use dec2flt::fpu::set_precision;
use crate::num::imp::dec2flt;
const INT_POW10: [u64; 16] = [
1,
@@ -9,7 +9,9 @@
//! algorithm can be found in "ParseNumberF64 by Simple Decimal Conversion",
//! available online: <https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html>.
use crate::num::dec2flt::common::{ByteSlice, is_8digits};
use dec2flt::common::{ByteSlice, is_8digits};
use crate::num::imp::dec2flt;
/// A decimal floating-point number, represented as a sequence of decimal digits.
#[derive(Clone, Debug, PartialEq)]
@@ -1,10 +1,10 @@
//! Implementation of the Eisel-Lemire algorithm.
use crate::num::dec2flt::common::BiasedFp;
use crate::num::dec2flt::float::RawFloat;
use crate::num::dec2flt::table::{
LARGEST_POWER_OF_FIVE, POWER_OF_FIVE_128, SMALLEST_POWER_OF_FIVE,
};
use dec2flt::common::BiasedFp;
use dec2flt::float::RawFloat;
use dec2flt::table::{LARGEST_POWER_OF_FIVE, POWER_OF_FIVE_128, SMALLEST_POWER_OF_FIVE};
use crate::num::imp::dec2flt;
/// Compute w * 10^q using an extended-precision float representation.
///
@@ -1,8 +1,10 @@
//! Functions to parse floating-point numbers.
use crate::num::dec2flt::common::{ByteSlice, is_8digits};
use crate::num::dec2flt::decimal::Decimal;
use crate::num::dec2flt::float::RawFloat;
use dec2flt::common::{ByteSlice, is_8digits};
use dec2flt::decimal::Decimal;
use dec2flt::float::RawFloat;
use crate::num::imp::dec2flt;
const MIN_19DIGIT_INT: u64 = 100_0000_0000_0000_0000;
@@ -1,8 +1,10 @@
//! Slow, fallback algorithm for cases the Eisel-Lemire algorithm cannot round.
use crate::num::dec2flt::common::BiasedFp;
use crate::num::dec2flt::decimal_seq::{DecimalSeq, parse_decimal_seq};
use crate::num::dec2flt::float::RawFloat;
use dec2flt::common::BiasedFp;
use dec2flt::decimal_seq::{DecimalSeq, parse_decimal_seq};
use dec2flt::float::RawFloat;
use crate::num::imp::dec2flt;
/// Parse the significant digits and biased, binary exponent of a float.
///
@@ -1,7 +1,7 @@
//! Decodes a floating-point value into individual parts and error ranges.
use crate::num::FpCategory;
use crate::num::dec2flt::float::RawFloat;
use crate::num::imp::dec2flt::float::RawFloat;
/// Decoded unsigned finite value, such that:
///
@@ -4,11 +4,13 @@
//! [^1]: Burger, R. G. and Dybvig, R. K. 1996. Printing floating-point numbers
//! quickly and accurately. SIGPLAN Not. 31, 5 (May. 1996), 108-116.
use flt2dec::estimator::estimate_scaling_factor;
use flt2dec::{Decoded, MAX_SIG_DIGITS, round_up};
use crate::cmp::Ordering;
use crate::mem::MaybeUninit;
use crate::num::bignum::{Big32x40 as Big, Digit32 as Digit};
use crate::num::flt2dec::estimator::estimate_scaling_factor;
use crate::num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up};
use crate::num::imp::bignum::{Big32x40 as Big, Digit32 as Digit};
use crate::num::imp::flt2dec;
static POW10: [Digit; 10] =
[1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000];
@@ -5,9 +5,11 @@
//! [^1]: Florian Loitsch. 2010. Printing floating-point numbers quickly and
//! accurately with integers. SIGPLAN Not. 45, 6 (June 2010), 233-243.
use flt2dec::{Decoded, MAX_SIG_DIGITS, round_up};
use crate::mem::MaybeUninit;
use crate::num::diy_float::Fp;
use crate::num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up};
use crate::num::imp::diy_float::Fp;
use crate::num::imp::flt2dec;
// see the comments in `format_shortest_opt` for the rationale.
#[doc(hidden)]
@@ -455,7 +457,7 @@ pub fn format_shortest<'a>(
d: &Decoded,
buf: &'a mut [MaybeUninit<u8>],
) -> (/*digits*/ &'a [u8], /*exp*/ i16) {
use crate::num::flt2dec::strategy::dragon::format_shortest as fallback;
use flt2dec::strategy::dragon::format_shortest as fallback;
// SAFETY: The borrow checker is not smart enough to let us use `buf`
// in the second branch, so we launder the lifetime here. But we only re-use
// `buf` if `format_shortest_opt` returned `None` so this is okay.
@@ -765,7 +767,7 @@ pub fn format_exact<'a>(
buf: &'a mut [MaybeUninit<u8>],
limit: i16,
) -> (/*digits*/ &'a [u8], /*exp*/ i16) {
use crate::num::flt2dec::strategy::dragon::format_exact as fallback;
use flt2dec::strategy::dragon::format_exact as fallback;
// SAFETY: The borrow checker is not smart enough to let us use `buf`
// in the second branch, so we launder the lifetime here. But we only re-use
// `buf` if `format_exact_opt` returned `None` so this is okay.
@@ -64,7 +64,7 @@
macro_rules! uint_impl {
($U:ident) => {
pub(super) mod $U {
pub(in crate::num) mod $U {
const STAGES: usize = $U::BITS.ilog2() as usize;
#[inline]
const fn prepare(sparse: $U) -> [$U; STAGES] {
@@ -100,7 +100,7 @@ pub(super) mod $U {
}
#[inline(always)]
pub(in super::super) const fn extract_impl(mut x: $U, sparse: $U) -> $U {
pub(in crate::num) const fn extract_impl(mut x: $U, sparse: $U) -> $U {
let masks = prepare(sparse);
x &= sparse;
let mut stage = 0;
@@ -131,7 +131,7 @@ pub(in super::super) const fn extract_impl(mut x: $U, sparse: $U) -> $U {
x
}
#[inline(always)]
pub(in super::super) const fn deposit_impl(mut x: $U, sparse: $U) -> $U {
pub(in crate::num) const fn deposit_impl(mut x: $U, sparse: $U) -> $U {
let masks = prepare(sparse);
let mut stage = STAGES;
while stage > 0 {
@@ -96,7 +96,7 @@ const fn u128_impl(mut val: u128) -> u32 {
macro_rules! define_unsigned_ilog10 {
($($ty:ident => $impl_fn:ident,)*) => {$(
#[inline]
pub(super) const fn $ty(val: NonZero<$ty>) -> u32 {
pub(in crate::num) const fn $ty(val: NonZero<$ty>) -> u32 {
let result = $impl_fn(val.get());
// SAFETY: Integer logarithm is monotonic non-decreasing, so the computed `result` cannot
@@ -117,7 +117,7 @@ pub(super) const fn $ty(val: NonZero<$ty>) -> u32 {
}
#[inline]
pub(super) const fn usize(val: NonZero<usize>) -> u32 {
pub(in crate::num) const fn usize(val: NonZero<usize>) -> u32 {
#[cfg(target_pointer_width = "16")]
let impl_fn = u16;
@@ -136,7 +136,7 @@ macro_rules! define_signed_ilog10 {
($($ty:ident => $impl_fn:ident,)*) => {$(
// 0 < val <= $ty::MAX
#[inline]
pub(super) const fn $ty(val: $ty) -> Option<u32> {
pub(in crate::num) const fn $ty(val: $ty) -> Option<u32> {
if val > 0 {
let result = $impl_fn(val.cast_unsigned());
@@ -166,6 +166,6 @@ pub(super) const fn $ty(val: $ty) -> Option<u32> {
/// on every single primitive type.
#[cold]
#[track_caller]
pub(super) const fn panic_for_nonpositive_argument() -> ! {
pub(in crate::num) const fn panic_for_nonpositive_argument() -> ! {
panic!("argument of integer logarithm must be positive")
}
@@ -37,7 +37,7 @@
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub(super) const fn u8(n: u8) -> u8 {
pub(in crate::num) const fn u8(n: u8) -> u8 {
U8_ISQRT_WITH_REMAINDER[n as usize].0
}
@@ -58,7 +58,7 @@ macro_rules! signed_fn {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub(super) const unsafe fn $SignedT(n: $SignedT) -> $SignedT {
pub(in crate::num) const unsafe fn $SignedT(n: $SignedT) -> $SignedT {
debug_assert!(n >= 0, "Negative input inside `isqrt`.");
$UnsignedT(n as $UnsignedT) as $SignedT
}
@@ -83,7 +83,7 @@ macro_rules! unsigned_fn {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub(super) const fn $UnsignedT(mut n: $UnsignedT) -> $UnsignedT {
pub(in crate::num) const fn $UnsignedT(mut n: $UnsignedT) -> $UnsignedT {
if n <= <$HalfBitsT>::MAX as $UnsignedT {
$HalfBitsT(n as $HalfBitsT) as $UnsignedT
} else {
@@ -311,6 +311,6 @@ const fn u128_stages(n: u128) -> u128 {
/// on every single primitive type.
#[cold]
#[track_caller]
pub(super) const fn panic_for_negative_argument() -> ! {
pub(in crate::num) const fn panic_for_negative_argument() -> ! {
panic!("argument of integer square root cannot be negative")
}
+18
View File
@@ -0,0 +1,18 @@
//! Numeric routines, separate from API.
// These modules are public only for testing.
#[cfg(not(no_fp_fmt_parse))]
pub mod bignum;
#[cfg(not(no_fp_fmt_parse))]
pub mod dec2flt;
#[cfg(not(no_fp_fmt_parse))]
pub mod diy_float;
#[cfg(not(no_fp_fmt_parse))]
pub mod flt2dec;
pub mod fmt;
pub(crate) mod int_bits;
pub(crate) mod int_log10;
pub(crate) mod int_sqrt;
pub(crate) mod libm;
pub(crate) mod overflow_panic;
@@ -4,48 +4,48 @@
#[cold]
#[track_caller]
pub(super) const fn add() -> ! {
pub(in crate::num) const fn add() -> ! {
panic!("attempt to add with overflow")
}
#[cold]
#[track_caller]
pub(super) const fn sub() -> ! {
pub(in crate::num) const fn sub() -> ! {
panic!("attempt to subtract with overflow")
}
#[cold]
#[track_caller]
pub(super) const fn mul() -> ! {
pub(in crate::num) const fn mul() -> ! {
panic!("attempt to multiply with overflow")
}
#[cold]
#[track_caller]
pub(super) const fn div() -> ! {
pub(in crate::num) const fn div() -> ! {
panic!("attempt to divide with overflow")
}
#[cold]
#[track_caller]
pub(super) const fn rem() -> ! {
pub(in crate::num) const fn rem() -> ! {
panic!("attempt to calculate the remainder with overflow")
}
#[cold]
#[track_caller]
pub(super) const fn neg() -> ! {
pub(in crate::num) const fn neg() -> ! {
panic!("attempt to negate with overflow")
}
#[cold]
#[track_caller]
pub(super) const fn shr() -> ! {
pub(in crate::num) const fn shr() -> ! {
panic!("attempt to shift right with overflow")
}
#[cold]
#[track_caller]
pub(super) const fn shl() -> ! {
pub(in crate::num) const fn shl() -> ! {
panic!("attempt to shift left with overflow")
}
+19 -19
View File
@@ -553,7 +553,7 @@ pub const fn checked_add(self, rhs: Self) -> Option<Self> {
#[track_caller]
pub const fn strict_add(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_add(rhs);
if b { overflow_panic::add() } else { a }
if b { imp::overflow_panic::add() } else { a }
}
/// Unchecked integer addition. Computes `self + rhs`, assuming overflow
@@ -643,7 +643,7 @@ pub const fn checked_add_unsigned(self, rhs: $UnsignedT) -> Option<Self> {
#[track_caller]
pub const fn strict_add_unsigned(self, rhs: $UnsignedT) -> Self {
let (a, b) = self.overflowing_add_unsigned(rhs);
if b { overflow_panic::add() } else { a }
if b { imp::overflow_panic::add() } else { a }
}
/// Checked integer subtraction. Computes `self - rhs`, returning `None` if
@@ -693,7 +693,7 @@ pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
#[track_caller]
pub const fn strict_sub(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_sub(rhs);
if b { overflow_panic::sub() } else { a }
if b { imp::overflow_panic::sub() } else { a }
}
/// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
@@ -783,7 +783,7 @@ pub const fn checked_sub_unsigned(self, rhs: $UnsignedT) -> Option<Self> {
#[track_caller]
pub const fn strict_sub_unsigned(self, rhs: $UnsignedT) -> Self {
let (a, b) = self.overflowing_sub_unsigned(rhs);
if b { overflow_panic::sub() } else { a }
if b { imp::overflow_panic::sub() } else { a }
}
/// Checked integer multiplication. Computes `self * rhs`, returning `None` if
@@ -833,7 +833,7 @@ pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
#[track_caller]
pub const fn strict_mul(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_mul(rhs);
if b { overflow_panic::mul() } else { a }
if b { imp::overflow_panic::mul() } else { a }
}
/// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
@@ -940,7 +940,7 @@ pub const fn checked_div(self, rhs: Self) -> Option<Self> {
#[track_caller]
pub const fn strict_div(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_div(rhs);
if b { overflow_panic::div() } else { a }
if b { imp::overflow_panic::div() } else { a }
}
/// Checked Euclidean division. Computes `self.div_euclid(rhs)`,
@@ -1007,7 +1007,7 @@ pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
#[track_caller]
pub const fn strict_div_euclid(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_div_euclid(rhs);
if b { overflow_panic::div() } else { a }
if b { imp::overflow_panic::div() } else { a }
}
/// Checked integer division without remainder. Computes `self / rhs`,
@@ -1179,7 +1179,7 @@ pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
#[track_caller]
pub const fn strict_rem(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_rem(rhs);
if b { overflow_panic::rem() } else { a }
if b { imp::overflow_panic::rem() } else { a }
}
/// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None`
@@ -1245,7 +1245,7 @@ pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
#[track_caller]
pub const fn strict_rem_euclid(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_rem_euclid(rhs);
if b { overflow_panic::rem() } else { a }
if b { imp::overflow_panic::rem() } else { a }
}
/// Checked negation. Computes `-self`, returning `None` if `self == MIN`.
@@ -1323,7 +1323,7 @@ pub const fn checked_neg(self) -> Option<Self> {
#[track_caller]
pub const fn strict_neg(self) -> Self {
let (a, b) = self.overflowing_neg();
if b { overflow_panic::neg() } else { a }
if b { imp::overflow_panic::neg() } else { a }
}
/// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger
@@ -1379,7 +1379,7 @@ pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
#[track_caller]
pub const fn strict_shl(self, rhs: u32) -> Self {
let (a, b) = self.overflowing_shl(rhs);
if b { overflow_panic::shl() } else { a }
if b { imp::overflow_panic::shl() } else { a }
}
/// Unchecked shift left. Computes `self << rhs`, assuming that
@@ -1558,7 +1558,7 @@ pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
#[track_caller]
pub const fn strict_shr(self, rhs: u32) -> Self {
let (a, b) = self.overflowing_shr(rhs);
if b { overflow_panic::shr() } else { a }
if b { imp::overflow_panic::shr() } else { a }
}
/// Unchecked shift right. Computes `self >> rhs`, assuming that
@@ -1847,7 +1847,7 @@ pub const fn checked_isqrt(self) -> Option<Self> {
} else {
// SAFETY: Input is nonnegative in this `else` branch.
let result = unsafe {
crate::num::int_sqrt::$ActualT(self as $ActualT) as $SelfT
imp::int_sqrt::$ActualT(self as $ActualT) as $SelfT
};
// Inform the optimizer what the range of outputs is. If
@@ -1864,7 +1864,7 @@ pub const fn checked_isqrt(self) -> Option<Self> {
unsafe {
// SAFETY: `<$ActualT>::MAX` is nonnegative.
const MAX_RESULT: $SelfT = unsafe {
crate::num::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT
imp::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT
};
crate::hint::assert_unchecked(result >= 0);
@@ -3134,7 +3134,7 @@ pub const fn pow(self, mut exp: u32) -> Self {
pub const fn isqrt(self) -> Self {
match self.checked_isqrt() {
Some(sqrt) => sqrt,
None => crate::num::int_sqrt::panic_for_negative_argument(),
None => imp::int_sqrt::panic_for_negative_argument(),
}
}
@@ -3440,7 +3440,7 @@ pub const fn ilog(self, base: Self) -> u32 {
if let Some(log) = self.checked_ilog(base) {
log
} else {
int_log10::panic_for_nonpositive_argument()
imp::int_log10::panic_for_nonpositive_argument()
}
}
@@ -3465,7 +3465,7 @@ pub const fn ilog2(self) -> u32 {
if let Some(log) = self.checked_ilog2() {
log
} else {
int_log10::panic_for_nonpositive_argument()
imp::int_log10::panic_for_nonpositive_argument()
}
}
@@ -3490,7 +3490,7 @@ pub const fn ilog10(self) -> u32 {
if let Some(log) = self.checked_ilog10() {
log
} else {
int_log10::panic_for_nonpositive_argument()
imp::int_log10::panic_for_nonpositive_argument()
}
}
@@ -3562,7 +3562,7 @@ pub const fn checked_ilog2(self) -> Option<u32> {
without modifying the original"]
#[inline]
pub const fn checked_ilog10(self) -> Option<u32> {
int_log10::$ActualT(self as $ActualT)
imp::int_log10::$ActualT(self as $ActualT)
}
/// Computes the absolute value of `self`.
+11 -18
View File
@@ -27,16 +27,14 @@ macro_rules! sign_dependent_expr {
};
}
// All these modules are technically private and only exposed for coretests:
#[cfg(not(no_fp_fmt_parse))]
pub mod bignum;
#[cfg(not(no_fp_fmt_parse))]
pub mod dec2flt;
#[cfg(not(no_fp_fmt_parse))]
pub mod diy_float;
#[cfg(not(no_fp_fmt_parse))]
pub mod flt2dec;
pub mod fmt;
// These modules are public only for testing.
#[doc(hidden)]
#[unstable(
feature = "num_internals",
reason = "internal routines only exposed for testing",
issue = "none"
)]
pub mod imp;
#[macro_use]
mod int_macros; // import int_impl!
@@ -44,12 +42,7 @@ macro_rules! sign_dependent_expr {
mod uint_macros; // import uint_impl!
mod error;
mod int_bits;
mod int_log10;
mod int_sqrt;
pub(crate) mod libm;
mod nonzero;
mod overflow_panic;
mod saturating;
mod wrapping;
@@ -57,15 +50,15 @@ macro_rules! sign_dependent_expr {
#[doc(hidden)]
pub mod niche_types;
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(no_fp_fmt_parse))]
pub use dec2flt::ParseFloatError;
#[stable(feature = "int_error_matching", since = "1.55.0")]
pub use error::IntErrorKind;
#[stable(feature = "rust1", since = "1.0.0")]
pub use error::ParseIntError;
#[stable(feature = "try_from", since = "1.34.0")]
pub use error::TryFromIntError;
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(no_fp_fmt_parse))]
pub use imp::dec2flt::ParseFloatError;
#[stable(feature = "generic_nonzero", since = "1.79.0")]
pub use nonzero::NonZero;
#[unstable(
+2 -1
View File
@@ -5,6 +5,7 @@
use crate::cmp::Ordering;
use crate::hash::{Hash, Hasher};
use crate::marker::{Destruct, Freeze, StructuralPartialEq};
use crate::num::imp;
use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign};
use crate::panic::{RefUnwindSafe, UnwindSafe};
use crate::str::FromStr;
@@ -1817,7 +1818,7 @@ pub const fn ilog2(self) -> u32 {
without modifying the original"]
#[inline]
pub const fn ilog10(self) -> u32 {
super::int_log10::$Int(self)
imp::int_log10::$Int(self)
}
/// Calculates the midpoint (average) between `self` and `rhs`.
+15 -15
View File
@@ -515,7 +515,7 @@ pub const fn swap_bytes(self) -> Self {
without modifying the original"]
#[inline]
pub const fn extract_bits(self, mask: Self) -> Self {
crate::num::int_bits::$ActualT::extract_impl(self as $ActualT, mask as $ActualT) as $SelfT
imp::int_bits::$ActualT::extract_impl(self as $ActualT, mask as $ActualT) as $SelfT
}
/// Returns an integer with the least significant bits of `self`
@@ -532,7 +532,7 @@ pub const fn extract_bits(self, mask: Self) -> Self {
without modifying the original"]
#[inline]
pub const fn deposit_bits(self, mask: Self) -> Self {
crate::num::int_bits::$ActualT::deposit_impl(self as $ActualT, mask as $ActualT) as $SelfT
imp::int_bits::$ActualT::deposit_impl(self as $ActualT, mask as $ActualT) as $SelfT
}
/// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
@@ -743,7 +743,7 @@ pub const fn checked_add(self, rhs: Self) -> Option<Self> {
#[track_caller]
pub const fn strict_add(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_add(rhs);
if b { overflow_panic::add() } else { a }
if b { imp::overflow_panic::add() } else { a }
}
/// Unchecked integer addition. Computes `self + rhs`, assuming overflow
@@ -838,7 +838,7 @@ pub const fn checked_add_signed(self, rhs: $SignedT) -> Option<Self> {
#[track_caller]
pub const fn strict_add_signed(self, rhs: $SignedT) -> Self {
let (a, b) = self.overflowing_add_signed(rhs);
if b { overflow_panic::add() } else { a }
if b { imp::overflow_panic::add() } else { a }
}
/// Checked integer subtraction. Computes `self - rhs`, returning
@@ -897,7 +897,7 @@ pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
#[track_caller]
pub const fn strict_sub(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_sub(rhs);
if b { overflow_panic::sub() } else { a }
if b { imp::overflow_panic::sub() } else { a }
}
/// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
@@ -1022,7 +1022,7 @@ pub const fn checked_sub_signed(self, rhs: $SignedT) -> Option<Self> {
#[track_caller]
pub const fn strict_sub_signed(self, rhs: $SignedT) -> Self {
let (a, b) = self.overflowing_sub_signed(rhs);
if b { overflow_panic::sub() } else { a }
if b { imp::overflow_panic::sub() } else { a }
}
#[doc = concat!(
@@ -1131,7 +1131,7 @@ pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
#[track_caller]
pub const fn strict_mul(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_mul(rhs);
if b { overflow_panic::mul() } else { a }
if b { imp::overflow_panic::mul() } else { a }
}
/// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
@@ -1556,7 +1556,7 @@ pub const fn ilog(self, base: Self) -> u32 {
if let Some(log) = self.checked_ilog(base) {
log
} else {
int_log10::panic_for_nonpositive_argument()
imp::int_log10::panic_for_nonpositive_argument()
}
}
@@ -1581,7 +1581,7 @@ pub const fn ilog2(self) -> u32 {
if let Some(log) = self.checked_ilog2() {
log
} else {
int_log10::panic_for_nonpositive_argument()
imp::int_log10::panic_for_nonpositive_argument()
}
}
@@ -1606,7 +1606,7 @@ pub const fn ilog10(self) -> u32 {
if let Some(log) = self.checked_ilog10() {
log
} else {
int_log10::panic_for_nonpositive_argument()
imp::int_log10::panic_for_nonpositive_argument()
}
}
@@ -1768,7 +1768,7 @@ pub const fn checked_neg(self) -> Option<Self> {
#[track_caller]
pub const fn strict_neg(self) -> Self {
let (a, b) = self.overflowing_neg();
if b { overflow_panic::neg() } else { a }
if b { imp::overflow_panic::neg() } else { a }
}
/// Checked shift left. Computes `self << rhs`, returning `None`
@@ -1824,7 +1824,7 @@ pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
#[track_caller]
pub const fn strict_shl(self, rhs: u32) -> Self {
let (a, b) = self.overflowing_shl(rhs);
if b { overflow_panic::shl() } else { a }
if b { imp::overflow_panic::shl() } else { a }
}
/// Unchecked shift left. Computes `self << rhs`, assuming that
@@ -2009,7 +2009,7 @@ pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
#[track_caller]
pub const fn strict_shr(self, rhs: u32) -> Self {
let (a, b) = self.overflowing_shr(rhs);
if b { overflow_panic::shr() } else { a }
if b { imp::overflow_panic::shr() } else { a }
}
/// Unchecked shift right. Computes `self >> rhs`, assuming that
@@ -3481,7 +3481,7 @@ pub const fn pow(self, mut exp: u32) -> Self {
without modifying the original"]
#[inline]
pub const fn isqrt(self) -> Self {
let result = crate::num::int_sqrt::$ActualT(self as $ActualT) as $SelfT;
let result = imp::int_sqrt::$ActualT(self as $ActualT) as $SelfT;
// Inform the optimizer what the range of outputs is. If testing
// `core` crashes with no panic message and a `num::int_sqrt::u*`
@@ -3494,7 +3494,7 @@ pub const fn isqrt(self) -> Self {
// integers is bounded by `[0, <$ActualT>::MAX]`, sqrt(n) will be
// bounded by `[sqrt(0), sqrt(<$ActualT>::MAX)]`.
unsafe {
const MAX_RESULT: $SelfT = crate::num::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT;
const MAX_RESULT: $SelfT = imp::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT;
crate::hint::assert_unchecked(result <= MAX_RESULT);
}
+1 -1
View File
@@ -3,7 +3,7 @@ mod strategy {
mod grisu;
}
use core::num::flt2dec::{DecodableFloat, Decoded, FullDecoded, MAX_SIG_DIGITS, decode};
use core::num::imp::flt2dec::{DecodableFloat, Decoded, FullDecoded, MAX_SIG_DIGITS, decode};
use std::io::Write;
use test::{Bencher, black_box};
@@ -1,4 +1,4 @@
use core::num::flt2dec::strategy::dragon::*;
use core::num::imp::flt2dec::strategy::dragon::*;
use std::mem::MaybeUninit;
use super::super::*;
@@ -1,4 +1,4 @@
use core::num::flt2dec::strategy::grisu::*;
use core::num::imp::flt2dec::strategy::grisu::*;
use std::mem::MaybeUninit;
use super::super::*;
+2 -2
View File
@@ -1,5 +1,5 @@
use core::num::bignum::Big32x40;
use core::num::bignum::tests::Big8x3 as Big;
use core::num::imp::bignum::Big32x40;
use core::num::imp::bignum::tests::Big8x3 as Big;
#[test]
#[should_panic]
@@ -1,4 +1,4 @@
use core::num::dec2flt::decimal::Decimal;
use core::num::imp::dec2flt::decimal::Decimal;
type FPath<F> = ((i64, u64, bool, bool), Option<F>);
@@ -1,4 +1,4 @@
use core::num::dec2flt::decimal_seq::{DecimalSeq, parse_decimal_seq};
use core::num::imp::dec2flt::decimal_seq::{DecimalSeq, parse_decimal_seq};
#[test]
fn test_trim() {
+1 -1
View File
@@ -1,4 +1,4 @@
use core::num::dec2flt::float::RawFloat;
use core::num::imp::dec2flt::float::RawFloat;
use crate::num::{ldexp_f32, ldexp_f64};
@@ -1,5 +1,7 @@
use core::num::dec2flt::float::RawFloat;
use core::num::dec2flt::lemire::compute_float;
use core::num::imp::dec2flt;
use dec2flt::float::RawFloat;
use dec2flt::lemire::compute_float;
#[cfg(target_has_reliable_f16)]
fn compute_float16(q: i64, w: u64) -> (i32, u64) {
+5 -3
View File
@@ -1,6 +1,8 @@
use core::num::dec2flt::decimal::Decimal;
use core::num::dec2flt::parse::parse_number;
use core::num::dec2flt::{dec2flt, pfe_invalid};
use core::num::imp::dec2flt;
use dec2flt::decimal::Decimal;
use dec2flt::parse::parse_number;
use dec2flt::{dec2flt, pfe_invalid};
fn new_dec(e: i64, m: u64) -> Decimal {
Decimal { exponent: e, mantissa: m, negative: false, many_digits: false }
@@ -1,4 +1,4 @@
use core::num::flt2dec::estimator::*;
use core::num::imp::flt2dec::estimator::*;
use crate::num::ldexp_f64;
+4 -10
View File
@@ -1,11 +1,13 @@
use core::num::flt2dec::{
use core::num::imp::flt2dec::{
DecodableFloat, Decoded, FullDecoded, MAX_SIG_DIGITS, Sign, decode, round_up, to_exact_exp_str,
to_exact_fixed_str, to_shortest_exp_str, to_shortest_str,
};
use core::num::fmt::{Formatted, Part};
use core::num::imp::fmt::{Formatted, Part};
use std::mem::MaybeUninit;
use std::{fmt, str};
use Sign::{Minus, MinusPlus};
use crate::num::{ldexp_f32, ldexp_f64};
mod estimator;
@@ -562,8 +564,6 @@ pub fn to_shortest_str_test<F>(mut f_: F)
where
F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
{
use core::num::flt2dec::Sign::*;
fn to_string<T, F>(f: &mut F, v: T, sign: Sign, frac_digits: usize) -> String
where
T: DecodableFloat,
@@ -672,8 +672,6 @@ pub fn to_shortest_exp_str_test<F>(mut f_: F)
where
F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
{
use core::num::flt2dec::Sign::*;
fn to_string<T, F>(f: &mut F, v: T, sign: Sign, exp_bounds: (i16, i16), upper: bool) -> String
where
T: DecodableFloat,
@@ -789,8 +787,6 @@ pub fn to_exact_exp_str_test<F>(mut f_: F)
where
F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
{
use core::num::flt2dec::Sign::*;
fn to_string<T, F>(f: &mut F, v: T, sign: Sign, ndigits: usize, upper: bool) -> String
where
T: DecodableFloat,
@@ -1065,8 +1061,6 @@ pub fn to_exact_fixed_str_test<F>(mut f_: F)
where
F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
{
use core::num::flt2dec::Sign::*;
fn to_string<T, F>(f: &mut F, v: T, sign: Sign, frac_digits: usize) -> String
where
T: DecodableFloat,
+10 -9
View File
@@ -1,10 +1,11 @@
#![cfg(not(target_arch = "wasm32"))]
use core::num::flt2dec::strategy::grisu::{format_exact_opt, format_shortest_opt};
use core::num::flt2dec::{DecodableFloat, Decoded, FullDecoded, MAX_SIG_DIGITS, decode};
use core::num::imp::flt2dec;
use std::mem::MaybeUninit;
use std::str;
use flt2dec::strategy::grisu::{format_exact_opt, format_shortest_opt};
use flt2dec::{DecodableFloat, Decoded, FullDecoded, MAX_SIG_DIGITS, decode};
use rand::distr::{Distribution, Uniform};
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
@@ -159,7 +160,7 @@ pub fn f32_exhaustive_equivalence_test<F, G>(f: F, g: G, k: usize)
#[test]
fn shortest_random_equivalence_test() {
use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
use flt2dec::strategy::dragon::format_shortest as fallback;
// Miri is too slow
let n = if cfg!(miri) { 10 } else { 10_000 };
@@ -174,7 +175,7 @@ fn shortest_random_equivalence_test() {
#[cfg(target_has_reliable_f16)]
fn shortest_f16_exhaustive_equivalence_test() {
// see the f32 version
use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
use flt2dec::strategy::dragon::format_shortest as fallback;
f16_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS);
}
@@ -188,7 +189,7 @@ fn shortest_f32_exhaustive_equivalence_test() {
// with `--nocapture` (and plenty of time and appropriate rustc flags), this should print:
// `done, ignored=17643158 passed=2121451881 failed=0`.
use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
use flt2dec::strategy::dragon::format_shortest as fallback;
f32_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS);
}
@@ -197,14 +198,14 @@ fn shortest_f32_exhaustive_equivalence_test() {
fn shortest_f64_hard_random_equivalence_test() {
// this again probably has to use appropriate rustc flags.
use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
use flt2dec::strategy::dragon::format_shortest as fallback;
f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 100_000_000);
}
#[test]
#[cfg(target_has_reliable_f16)]
fn exact_f16_random_equivalence_test() {
use core::num::flt2dec::strategy::dragon::format_exact as fallback;
use flt2dec::strategy::dragon::format_exact as fallback;
// Miri is too slow
let n = if cfg!(miri) { 3 } else { 1_000 };
@@ -220,7 +221,7 @@ fn exact_f16_random_equivalence_test() {
#[test]
fn exact_f32_random_equivalence_test() {
use core::num::flt2dec::strategy::dragon::format_exact as fallback;
use flt2dec::strategy::dragon::format_exact as fallback;
// Miri is too slow
let n = if cfg!(miri) { 3 } else { 1_000 };
@@ -236,7 +237,7 @@ fn exact_f32_random_equivalence_test() {
#[test]
fn exact_f64_random_equivalence_test() {
use core::num::flt2dec::strategy::dragon::format_exact as fallback;
use flt2dec::strategy::dragon::format_exact as fallback;
// Miri is too slow
let n = if cfg!(miri) { 2 } else { 1_000 };
@@ -1,5 +1,5 @@
use core::num::bignum::Big32x40 as Big;
use core::num::flt2dec::strategy::dragon::*;
use core::num::imp::bignum::Big32x40 as Big;
use core::num::imp::flt2dec::strategy::dragon::*;
use super::super::*;
@@ -1,4 +1,4 @@
use core::num::flt2dec::strategy::grisu::*;
use core::num::imp::flt2dec::strategy::grisu::*;
use super::super::*;
@@ -11,18 +11,18 @@
let mut _7: isize;
let mut _9: &mut std::fmt::Formatter<'_>;
let mut _10: &T;
let mut _11: core::num::flt2dec::Sign;
let mut _11: core::num::imp::flt2dec::Sign;
let mut _12: u32;
let mut _13: u32;
let mut _14: usize;
let mut _15: bool;
let mut _16: &mut std::fmt::Formatter<'_>;
let mut _17: &T;
let mut _18: core::num::flt2dec::Sign;
let mut _18: core::num::imp::flt2dec::Sign;
let mut _19: bool;
scope 1 {
debug force_sign => _4;
let _5: core::num::flt2dec::Sign;
let _5: core::num::imp::flt2dec::Sign;
scope 2 {
debug sign => _5;
scope 3 {
@@ -56,14 +56,14 @@
}
bb1: {
- _5 = core::num::flt2dec::Sign::MinusPlus;
+ _5 = const core::num::flt2dec::Sign::MinusPlus;
- _5 = core::num::imp::flt2dec::Sign::MinusPlus;
+ _5 = const core::num::imp::flt2dec::Sign::MinusPlus;
goto -> bb3;
}
bb2: {
- _5 = core::num::flt2dec::Sign::Minus;
+ _5 = const core::num::flt2dec::Sign::Minus;
- _5 = core::num::imp::flt2dec::Sign::Minus;
+ _5 = const core::num::imp::flt2dec::Sign::Minus;
goto -> bb3;
}
@@ -11,18 +11,18 @@
let mut _7: isize;
let mut _9: &mut std::fmt::Formatter<'_>;
let mut _10: &T;
let mut _11: core::num::flt2dec::Sign;
let mut _11: core::num::imp::flt2dec::Sign;
let mut _12: u32;
let mut _13: u32;
let mut _14: usize;
let mut _15: bool;
let mut _16: &mut std::fmt::Formatter<'_>;
let mut _17: &T;
let mut _18: core::num::flt2dec::Sign;
let mut _18: core::num::imp::flt2dec::Sign;
let mut _19: bool;
scope 1 {
debug force_sign => _4;
let _5: core::num::flt2dec::Sign;
let _5: core::num::imp::flt2dec::Sign;
scope 2 {
debug sign => _5;
scope 3 {
@@ -56,14 +56,14 @@
}
bb1: {
- _5 = core::num::flt2dec::Sign::MinusPlus;
+ _5 = const core::num::flt2dec::Sign::MinusPlus;
- _5 = core::num::imp::flt2dec::Sign::MinusPlus;
+ _5 = const core::num::imp::flt2dec::Sign::MinusPlus;
goto -> bb3;
}
bb2: {
- _5 = core::num::flt2dec::Sign::Minus;
+ _5 = const core::num::flt2dec::Sign::Minus;
- _5 = core::num::imp::flt2dec::Sign::Minus;
+ _5 = const core::num::imp::flt2dec::Sign::Minus;
goto -> bb3;
}
@@ -11,18 +11,18 @@
let mut _7: isize;
let mut _9: &mut std::fmt::Formatter<'_>;
let mut _10: &T;
let mut _11: core::num::flt2dec::Sign;
let mut _11: core::num::imp::flt2dec::Sign;
let mut _12: u32;
let mut _13: u32;
let mut _14: usize;
let mut _15: bool;
let mut _16: &mut std::fmt::Formatter<'_>;
let mut _17: &T;
let mut _18: core::num::flt2dec::Sign;
let mut _18: core::num::imp::flt2dec::Sign;
let mut _19: bool;
scope 1 {
debug force_sign => _4;
let _5: core::num::flt2dec::Sign;
let _5: core::num::imp::flt2dec::Sign;
scope 2 {
debug sign => _5;
scope 3 {
@@ -56,14 +56,14 @@
}
bb1: {
- _5 = core::num::flt2dec::Sign::MinusPlus;
+ _5 = const core::num::flt2dec::Sign::MinusPlus;
- _5 = core::num::imp::flt2dec::Sign::MinusPlus;
+ _5 = const core::num::imp::flt2dec::Sign::MinusPlus;
goto -> bb3;
}
bb2: {
- _5 = core::num::flt2dec::Sign::Minus;
+ _5 = const core::num::flt2dec::Sign::Minus;
- _5 = core::num::imp::flt2dec::Sign::Minus;
+ _5 = const core::num::imp::flt2dec::Sign::Minus;
goto -> bb3;
}
@@ -11,18 +11,18 @@
let mut _7: isize;
let mut _9: &mut std::fmt::Formatter<'_>;
let mut _10: &T;
let mut _11: core::num::flt2dec::Sign;
let mut _11: core::num::imp::flt2dec::Sign;
let mut _12: u32;
let mut _13: u32;
let mut _14: usize;
let mut _15: bool;
let mut _16: &mut std::fmt::Formatter<'_>;
let mut _17: &T;
let mut _18: core::num::flt2dec::Sign;
let mut _18: core::num::imp::flt2dec::Sign;
let mut _19: bool;
scope 1 {
debug force_sign => _4;
let _5: core::num::flt2dec::Sign;
let _5: core::num::imp::flt2dec::Sign;
scope 2 {
debug sign => _5;
scope 3 {
@@ -56,14 +56,14 @@
}
bb1: {
- _5 = core::num::flt2dec::Sign::MinusPlus;
+ _5 = const core::num::flt2dec::Sign::MinusPlus;
- _5 = core::num::imp::flt2dec::Sign::MinusPlus;
+ _5 = const core::num::imp::flt2dec::Sign::MinusPlus;
goto -> bb3;
}
bb2: {
- _5 = core::num::flt2dec::Sign::Minus;
+ _5 = const core::num::flt2dec::Sign::Minus;
- _5 = core::num::imp::flt2dec::Sign::Minus;
+ _5 = const core::num::imp::flt2dec::Sign::Minus;
goto -> bb3;
}
+2 -1
View File
@@ -3,10 +3,11 @@
// EMIT_MIR_FOR_EACH_BIT_WIDTH
#![feature(flt2dec)]
#![feature(num_internals)]
extern crate core;
use core::num::flt2dec;
use core::num::imp::flt2dec;
use std::fmt::{Formatter, Result};
// EMIT_MIR funky_arms.float_to_exponential_common.GVN.diff
+1 -1
View File
@@ -1076,7 +1076,7 @@ gets adapted for the changes, if necessary.
"""
cc = ["@rust-lang/miri", "@RalfJung", "@oli-obk", "@lcnr"]
[mentions."library/core/src/num/{dec2flt,flt2dec}"]
[mentions."library/core/src/num/imp/{dec2flt,flt2dec}"]
message = "Some changes occurred in float parsing"
cc = ["@tgross35"]