mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
dec2flt: Move internal traits to better locations
`Float` and `FloatExt` are already used by both parsing and printing, so move them out of `dec2flt` to a new module in `num::imp`. `Int` `Cast` have the potential to be used more places in the future, so move them there as well. `Lemire` is the only remaining trait; since it is small, move it into the `dec2flt` root. The `fmt::LowerExp` bound is removed from `Float` here since the trait is moving into a module without `#[cfg(not(no_fp_fmt_parse))]` and it isn't implemented with that config (it's not easily possible to add `cfg` attributes to a single supertrait, unfortunately). This isn't a problem since it isn't actually being used.
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
//! Representation of a float as the significant digits and exponent.
|
||||
|
||||
use crate::num::imp::dec2flt;
|
||||
use dec2flt::float::Lemire;
|
||||
use dec2flt::Lemire;
|
||||
use dec2flt::fpu::set_precision;
|
||||
|
||||
use crate::num::imp::dec2flt;
|
||||
|
||||
const INT_POW10: [u64; 16] = [
|
||||
1,
|
||||
10,
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
//! Implementation of the Eisel-Lemire algorithm.
|
||||
|
||||
use dec2flt::common::BiasedFp;
|
||||
use dec2flt::float::Float;
|
||||
use dec2flt::table::{LARGEST_POWER_OF_FIVE, POWER_OF_FIVE_128, SMALLEST_POWER_OF_FIVE};
|
||||
|
||||
use crate::num::imp::dec2flt;
|
||||
use crate::num::imp::{Float, dec2flt};
|
||||
|
||||
/// Compute w * 10^q using an extended-precision float representation.
|
||||
///
|
||||
|
||||
@@ -88,24 +88,104 @@
|
||||
)]
|
||||
|
||||
use common::BiasedFp;
|
||||
use float::{FloatExt, Lemire};
|
||||
use lemire::compute_float;
|
||||
use parse::{parse_inf_nan, parse_number};
|
||||
use slow::parse_long_mantissa;
|
||||
|
||||
use crate::f64;
|
||||
use crate::num::ParseFloatError;
|
||||
use crate::num::float_parse::FloatErrorKind;
|
||||
use crate::num::imp::FloatExt;
|
||||
|
||||
mod common;
|
||||
pub mod decimal;
|
||||
pub mod decimal_seq;
|
||||
mod fpu;
|
||||
mod slow;
|
||||
mod table;
|
||||
// float is used in flt2dec, and all are used in unit tests.
|
||||
pub mod float;
|
||||
pub mod lemire;
|
||||
pub mod parse;
|
||||
mod slow;
|
||||
mod table;
|
||||
|
||||
/// Extension to `Float` that are necessary for parsing using the Lemire method.
|
||||
///
|
||||
/// See the parent module's doc comment for why this is necessary.
|
||||
///
|
||||
/// Not intended for use outside of the `dec2flt` module.
|
||||
#[doc(hidden)]
|
||||
pub trait Lemire: FloatExt {
|
||||
/// Maximum exponent for a fast path case, or `⌊(SIG_BITS+1)/log2(5)⌋`
|
||||
// assuming FLT_EVAL_METHOD = 0
|
||||
const MAX_EXPONENT_FAST_PATH: i64 = {
|
||||
let log2_5 = f64::consts::LOG2_10 - 1.0;
|
||||
(Self::SIG_TOTAL_BITS as f64 / log2_5) as i64
|
||||
};
|
||||
|
||||
/// Minimum exponent for a fast path case, or `-⌊(SIG_BITS+1)/log2(5)⌋`
|
||||
const MIN_EXPONENT_FAST_PATH: i64 = -Self::MAX_EXPONENT_FAST_PATH;
|
||||
|
||||
/// Maximum exponent that can be represented for a disguised-fast path case.
|
||||
/// This is `MAX_EXPONENT_FAST_PATH + ⌊(SIG_BITS+1)/log2(10)⌋`
|
||||
const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 =
|
||||
Self::MAX_EXPONENT_FAST_PATH + (Self::SIG_TOTAL_BITS as f64 / f64::consts::LOG2_10) as i64;
|
||||
|
||||
/// Maximum mantissa for the fast-path (`1 << 53` for f64).
|
||||
const MAX_MANTISSA_FAST_PATH: u64 = 1 << Self::SIG_TOTAL_BITS;
|
||||
|
||||
/// Gets a small power-of-ten for fast-path multiplication.
|
||||
fn pow10_fast_path(exponent: usize) -> Self;
|
||||
|
||||
/// Converts integer into float through an as cast.
|
||||
/// This is only called in the fast-path algorithm, and therefore
|
||||
/// will not lose precision, since the value will always have
|
||||
/// only if the value is <= Self::MAX_MANTISSA_FAST_PATH.
|
||||
fn from_u64(v: u64) -> Self;
|
||||
}
|
||||
|
||||
#[cfg(target_has_reliable_f16)]
|
||||
impl Lemire for f16 {
|
||||
fn pow10_fast_path(exponent: usize) -> Self {
|
||||
#[allow(clippy::use_self)]
|
||||
const TABLE: [f16; 8] = [1e0, 1e1, 1e2, 1e3, 1e4, 0.0, 0.0, 0.];
|
||||
TABLE[exponent & 7]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_u64(v: u64) -> Self {
|
||||
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
|
||||
v as _
|
||||
}
|
||||
}
|
||||
|
||||
impl Lemire for f32 {
|
||||
fn pow10_fast_path(exponent: usize) -> Self {
|
||||
#[allow(clippy::use_self)]
|
||||
const TABLE: [f32; 16] =
|
||||
[1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.];
|
||||
TABLE[exponent & 15]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_u64(v: u64) -> Self {
|
||||
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
|
||||
v as _
|
||||
}
|
||||
}
|
||||
|
||||
impl Lemire for f64 {
|
||||
fn pow10_fast_path(exponent: usize) -> Self {
|
||||
const TABLE: [f64; 32] = [
|
||||
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
|
||||
1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0.,
|
||||
];
|
||||
TABLE[exponent & 31]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_u64(v: u64) -> Self {
|
||||
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
|
||||
v as _
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn pfe_empty() -> ParseFloatError {
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
use dec2flt::common::{ByteSlice, is_8digits};
|
||||
use dec2flt::decimal::Decimal;
|
||||
use dec2flt::float::Float;
|
||||
|
||||
use crate::num::imp::dec2flt;
|
||||
use crate::num::imp::{Float, dec2flt};
|
||||
|
||||
const MIN_19DIGIT_INT: u64 = 100_0000_0000_0000_0000;
|
||||
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
use dec2flt::common::BiasedFp;
|
||||
use dec2flt::decimal_seq::{DecimalSeq, parse_decimal_seq};
|
||||
use dec2flt::float::Float;
|
||||
|
||||
use crate::num::imp::dec2flt;
|
||||
use crate::num::imp::{Float, 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::imp::dec2flt::float::FloatExt;
|
||||
use crate::num::imp::FloatExt;
|
||||
|
||||
/// Decoded unsigned finite value, such that:
|
||||
///
|
||||
|
||||
@@ -16,3 +16,6 @@
|
||||
pub(crate) mod int_sqrt;
|
||||
pub(crate) mod libm;
|
||||
pub(crate) mod overflow_panic;
|
||||
mod traits;
|
||||
|
||||
pub use traits::{Float, FloatExt, Int};
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
//! Helper trait for generic float types.
|
||||
//! Numeric traits used for internal implementations.
|
||||
|
||||
use core::f64;
|
||||
#![doc(hidden)]
|
||||
#![unstable(
|
||||
feature = "num_internals",
|
||||
reason = "internal routines only exposed for testing",
|
||||
issue = "none"
|
||||
)]
|
||||
|
||||
use crate::fmt::{Debug, LowerExp};
|
||||
use crate::num::FpCategory;
|
||||
use crate::ops::{self, Add, Div, Mul, Neg};
|
||||
use crate::{f64, fmt, ops};
|
||||
|
||||
/// Lossy `as` casting between two types.
|
||||
pub trait CastInto<T: Copy>: Copy {
|
||||
@@ -16,7 +20,7 @@ pub trait Int:
|
||||
Sized
|
||||
+ Clone
|
||||
+ Copy
|
||||
+ Debug
|
||||
+ fmt::Debug
|
||||
+ ops::Shr<u32, Output = Self>
|
||||
+ ops::Shl<u32, Output = Self>
|
||||
+ ops::BitAnd<Output = Self>
|
||||
@@ -51,17 +55,16 @@ impl Int for $ty {
|
||||
#[doc(hidden)]
|
||||
pub trait Float:
|
||||
Sized
|
||||
+ Div<Output = Self>
|
||||
+ Neg<Output = Self>
|
||||
+ Mul<Output = Self>
|
||||
+ Add<Output = Self>
|
||||
+ LowerExp
|
||||
+ ops::Div<Output = Self>
|
||||
+ ops::Neg<Output = Self>
|
||||
+ ops::Mul<Output = Self>
|
||||
+ ops::Add<Output = Self>
|
||||
+ fmt::Debug
|
||||
+ PartialEq
|
||||
+ PartialOrd
|
||||
+ Default
|
||||
+ Clone
|
||||
+ Copy
|
||||
+ Debug
|
||||
{
|
||||
/// The unsigned integer with the same size as the float
|
||||
type Int: Int + Into<u64>;
|
||||
@@ -184,41 +187,6 @@ fn integer_decode(self) -> (u64, i16, i8) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension to `Float` that are necessary for parsing using the Lemire method.
|
||||
///
|
||||
/// See the parent module's doc comment for why this is necessary.
|
||||
///
|
||||
/// Not intended for use outside of the `dec2flt` module.
|
||||
#[doc(hidden)]
|
||||
pub trait Lemire: FloatExt {
|
||||
/// Maximum exponent for a fast path case, or `⌊(SIG_BITS+1)/log2(5)⌋`
|
||||
// assuming FLT_EVAL_METHOD = 0
|
||||
const MAX_EXPONENT_FAST_PATH: i64 = {
|
||||
let log2_5 = f64::consts::LOG2_10 - 1.0;
|
||||
(Self::SIG_TOTAL_BITS as f64 / log2_5) as i64
|
||||
};
|
||||
|
||||
/// Minimum exponent for a fast path case, or `-⌊(SIG_BITS+1)/log2(5)⌋`
|
||||
const MIN_EXPONENT_FAST_PATH: i64 = -Self::MAX_EXPONENT_FAST_PATH;
|
||||
|
||||
/// Maximum exponent that can be represented for a disguised-fast path case.
|
||||
/// This is `MAX_EXPONENT_FAST_PATH + ⌊(SIG_BITS+1)/log2(10)⌋`
|
||||
const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 =
|
||||
Self::MAX_EXPONENT_FAST_PATH + (Self::SIG_TOTAL_BITS as f64 / f64::consts::LOG2_10) as i64;
|
||||
|
||||
/// Maximum mantissa for the fast-path (`1 << 53` for f64).
|
||||
const MAX_MANTISSA_FAST_PATH: u64 = 1 << Self::SIG_TOTAL_BITS;
|
||||
|
||||
/// Gets a small power-of-ten for fast-path multiplication.
|
||||
fn pow10_fast_path(exponent: usize) -> Self;
|
||||
|
||||
/// Converts integer into float through an as cast.
|
||||
/// This is only called in the fast-path algorithm, and therefore
|
||||
/// will not lose precision, since the value will always have
|
||||
/// only if the value is <= Self::MAX_MANTISSA_FAST_PATH.
|
||||
fn from_u64(v: u64) -> Self;
|
||||
}
|
||||
|
||||
/// Solve for `b` in `10^b = 2^a`
|
||||
const fn pow2_to_pow10(a: i64) -> i64 {
|
||||
let res = (a as f64) / f64::consts::LOG2_10;
|
||||
@@ -260,21 +228,6 @@ fn from_u64_bits(v: u64) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_has_reliable_f16)]
|
||||
impl Lemire for f16 {
|
||||
fn pow10_fast_path(exponent: usize) -> Self {
|
||||
#[allow(clippy::use_self)]
|
||||
const TABLE: [f16; 8] = [1e0, 1e1, 1e2, 1e3, 1e4, 0.0, 0.0, 0.];
|
||||
TABLE[exponent & 7]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_u64(v: u64) -> Self {
|
||||
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
|
||||
v as _
|
||||
}
|
||||
}
|
||||
|
||||
impl Float for f32 {
|
||||
type Int = u32;
|
||||
|
||||
@@ -308,21 +261,6 @@ fn from_u64_bits(v: u64) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
impl Lemire for f32 {
|
||||
fn pow10_fast_path(exponent: usize) -> Self {
|
||||
#[allow(clippy::use_self)]
|
||||
const TABLE: [f32; 16] =
|
||||
[1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.];
|
||||
TABLE[exponent & 15]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_u64(v: u64) -> Self {
|
||||
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
|
||||
v as _
|
||||
}
|
||||
}
|
||||
|
||||
impl Float for f64 {
|
||||
type Int = u64;
|
||||
|
||||
@@ -355,19 +293,3 @@ fn from_u64_bits(v: u64) -> Self {
|
||||
f64::from_bits(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl Lemire for f64 {
|
||||
fn pow10_fast_path(exponent: usize) -> Self {
|
||||
const TABLE: [f64; 32] = [
|
||||
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
|
||||
1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0.,
|
||||
];
|
||||
TABLE[exponent & 31]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_u64(v: u64) -> Self {
|
||||
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
|
||||
v as _
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,7 @@
|
||||
#![feature(next_index)]
|
||||
#![feature(non_exhaustive_omitted_patterns_lint)]
|
||||
#![feature(nonzero_from_str_radix)]
|
||||
#![feature(num_internals)]
|
||||
#![feature(numfmt)]
|
||||
#![feature(one_sided_range)]
|
||||
#![feature(panic_internals)]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use core::num::imp::dec2flt::float::{Float, FloatExt, Lemire};
|
||||
use core::num::imp::dec2flt::Lemire;
|
||||
use core::num::imp::{Float, FloatExt};
|
||||
|
||||
use crate::num::{ldexp_f32, ldexp_f64};
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use core::num::imp::dec2flt;
|
||||
use core::num::imp::{Float, dec2flt};
|
||||
|
||||
use dec2flt::float::Float;
|
||||
use dec2flt::lemire::compute_float;
|
||||
|
||||
#[cfg(target_has_reliable_f16)]
|
||||
|
||||
Reference in New Issue
Block a user