Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion library/core/src/fmt/float.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::cell::{Cell, Ref, RefCell, RefMut, SyncUnsafeCell, UnsafeCell};
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};
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/fmt/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/num/f16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down
2 changes: 1 addition & 1 deletion library/core/src/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1633,7 +1633,7 @@ impl 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.
///
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/num/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1631,7 +1631,7 @@ impl 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.
///
Expand Down
133 changes: 133 additions & 0 deletions library/core/src/num/float_parse.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
//! User-facing API for float parsing.

use crate::error::Error;
use crate::fmt;
use crate::num::imp::dec2flt;
use crate::str::FromStr;

macro_rules! from_str_float_impl {
($t:ty) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for $t {
type Err = ParseFloatError;

/// Converts a string in base 10 to a float.
/// Accepts an optional decimal exponent.
///
/// This function accepts strings such as
///
/// * '3.14'
/// * '-3.14'
/// * '2.5E10', or equivalently, '2.5e10'
/// * '2.5E-10'
/// * '5.'
/// * '.5', or, equivalently, '0.5'
/// * '7'
/// * '007'
/// * 'inf', '-inf', '+infinity', 'NaN'
///
/// Note that alphabetical characters are not case-sensitive.
///
/// Leading and trailing whitespace represent an error.
///
/// # Grammar
///
/// All strings that adhere to the following [EBNF] grammar when
/// lowercased will result in an [`Ok`] being returned:
///
/// ```txt
/// Float ::= Sign? ( 'inf' | 'infinity' | 'nan' | Number )
/// Number ::= ( Digit+ |
/// Digit+ '.' Digit* |
/// Digit* '.' Digit+ ) Exp?
/// Exp ::= 'e' Sign? Digit+
/// Sign ::= [+-]
/// Digit ::= [0-9]
/// ```
///
/// [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation
///
/// # Arguments
///
/// * src - A string
///
/// # Return value
///
/// `Err(ParseFloatError)` if the string did not represent a valid
/// number. Otherwise, `Ok(n)` where `n` is the closest
/// representable floating-point number to the number represented
/// by `src` (following the same rules for rounding as for the
/// results of primitive operations).
// We add the `#[inline(never)]` attribute, since its content will
// be filled with that of `dec2flt`, which has #[inline(always)].
// Since `dec2flt` is generic, a normal inline attribute on this function
// with `dec2flt` having no attributes results in heavily repeated
// generation of `dec2flt`, despite the fact only a maximum of 2
// possible instances can ever exist. Adding #[inline(never)] avoids this.
#[inline(never)]
fn from_str(src: &str) -> Result<Self, ParseFloatError> {
dec2flt::dec2flt(src)
}
}
};
}

#[cfg(target_has_reliable_f16)]
from_str_float_impl!(f16);
from_str_float_impl!(f32);
from_str_float_impl!(f64);

// FIXME(f16): A fallback is used when the backend+target does not support f16 well, in order
// to avoid ICEs.

#[cfg(not(target_has_reliable_f16))]
#[expect(ineffective_unstable_trait_impl, reason = "stable trait on unstable type")]
#[unstable(feature = "f16", issue = "116909")]
impl FromStr for f16 {
type Err = ParseFloatError;

#[inline]
fn from_str(_src: &str) -> Result<Self, ParseFloatError> {
unimplemented!("requires target_has_reliable_f16")
}
}

/// An error which can be returned when parsing a float.
///
/// This error is used as the error type for the [`FromStr`] implementation
/// for [`f32`] and [`f64`].
///
/// # Example
///
/// ```
/// use std::str::FromStr;
///
/// if let Err(e) = f64::from_str("a.12") {
/// println!("Failed conversion to f64: {e}");
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseFloatError {
pub(super) kind: FloatErrorKind,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) enum FloatErrorKind {
Empty,
Invalid,
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Error for ParseFloatError {}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseFloatError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind {
FloatErrorKind::Empty => "cannot parse float from empty string",
FloatErrorKind::Invalid => "invalid float literal",
}
.fmt(f)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ macro_rules! define_bignum {

/// 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.
Expand Down Expand Up @@ -281,7 +281,7 @@ macro_rules! define_bignum {
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() {
Expand Down Expand Up @@ -320,7 +320,7 @@ macro_rules! define_bignum {
/// 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);

Expand Down
Original file line number Diff line number Diff line change
@@ -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::Lemire;
use dec2flt::fpu::set_precision;

use crate::num::imp::dec2flt;

const INT_POW10: [u64; 16] = [
1,
Expand Down Expand Up @@ -34,7 +36,7 @@ pub struct Decimal {
impl Decimal {
/// Detect if the float can be accurately reconstructed from native floats.
#[inline]
fn can_use_fast_path<F: RawFloat>(&self) -> bool {
fn can_use_fast_path<F: Lemire>(&self) -> bool {
F::MIN_EXPONENT_FAST_PATH <= self.exponent
&& self.exponent <= F::MAX_EXPONENT_DISGUISED_FAST_PATH
&& self.mantissa <= F::MAX_MANTISSA_FAST_PATH
Expand All @@ -51,7 +53,7 @@ impl Decimal {
///
/// There is an exception: disguised fast-path cases, where we can shift
/// powers-of-10 from the exponent to the significant digits.
pub fn try_fast_path<F: RawFloat>(&self) -> Option<F> {
pub fn try_fast_path<F: Lemire>(&self) -> Option<F> {
// Here we need to work around <https://github.com/rust-lang/rust/issues/114479>.
// The fast path crucially depends on arithmetic being rounded to the correct number of bits
// without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
//! 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::table::{LARGEST_POWER_OF_FIVE, POWER_OF_FIVE_128, SMALLEST_POWER_OF_FIVE};

use crate::num::imp::{Float, dec2flt};

/// Compute w * 10^q using an extended-precision float representation.
///
Expand All @@ -24,7 +23,7 @@ use crate::num::dec2flt::table::{
/// at a Gigabyte per Second" in section 5, "Fast Algorithm", and
/// section 6, "Exact Numbers And Ties", available online:
/// <https://arxiv.org/abs/2101.11408.pdf>.
pub fn compute_float<F: RawFloat>(q: i64, mut w: u64) -> BiasedFp {
pub fn compute_float<F: Float>(q: i64, mut w: u64) -> BiasedFp {
let fp_zero = BiasedFp::zero_pow2(0);
let fp_inf = BiasedFp::zero_pow2(F::INFINITE_POWER);
let fp_error = BiasedFp::zero_pow2(-1);
Expand Down
Loading
Loading