Skip to content

Commit ff1a43f

Browse files
committed
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.
1 parent 265f0f5 commit ff1a43f

File tree

12 files changed

+115
-109
lines changed

12 files changed

+115
-109
lines changed

library/core/src/num/float_parse.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ from_str_float_impl!(f64);
8181
// to avoid ICEs.
8282

8383
#[cfg(not(target_has_reliable_f16))]
84+
#[unstable(feature = "f16", issue = "116909")]
8485
impl FromStr for f16 {
8586
type Err = ParseFloatError;
8687

library/core/src/num/imp/dec2flt/decimal.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
//! Representation of a float as the significant digits and exponent.
22
3-
use crate::num::imp::dec2flt;
4-
use dec2flt::float::Lemire;
3+
use dec2flt::Lemire;
54
use dec2flt::fpu::set_precision;
65

6+
use crate::num::imp::dec2flt;
7+
78
const INT_POW10: [u64; 16] = [
89
1,
910
10,

library/core/src/num/imp/dec2flt/lemire.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
//! Implementation of the Eisel-Lemire algorithm.
22
33
use dec2flt::common::BiasedFp;
4-
use dec2flt::float::Float;
54
use dec2flt::table::{LARGEST_POWER_OF_FIVE, POWER_OF_FIVE_128, SMALLEST_POWER_OF_FIVE};
65

7-
use crate::num::imp::dec2flt;
6+
use crate::num::imp::{Float, dec2flt};
87

98
/// Compute w * 10^q using an extended-precision float representation.
109
///

library/core/src/num/imp/dec2flt/mod.rs

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,24 +88,104 @@
8888
)]
8989

9090
use common::BiasedFp;
91-
use float::{FloatExt, Lemire};
9291
use lemire::compute_float;
9392
use parse::{parse_inf_nan, parse_number};
9493
use slow::parse_long_mantissa;
9594

95+
use crate::f64;
9696
use crate::num::ParseFloatError;
9797
use crate::num::float_parse::FloatErrorKind;
98+
use crate::num::imp::FloatExt;
9899

99100
mod common;
100101
pub mod decimal;
101102
pub mod decimal_seq;
102103
mod fpu;
103-
mod slow;
104-
mod table;
105-
// float is used in flt2dec, and all are used in unit tests.
106-
pub mod float;
107104
pub mod lemire;
108105
pub mod parse;
106+
mod slow;
107+
mod table;
108+
109+
/// Extension to `Float` that are necessary for parsing using the Lemire method.
110+
///
111+
/// See the parent module's doc comment for why this is necessary.
112+
///
113+
/// Not intended for use outside of the `dec2flt` module.
114+
#[doc(hidden)]
115+
pub trait Lemire: FloatExt {
116+
/// Maximum exponent for a fast path case, or `⌊(SIG_BITS+1)/log2(5)⌋`
117+
// assuming FLT_EVAL_METHOD = 0
118+
const MAX_EXPONENT_FAST_PATH: i64 = {
119+
let log2_5 = f64::consts::LOG2_10 - 1.0;
120+
(Self::SIG_TOTAL_BITS as f64 / log2_5) as i64
121+
};
122+
123+
/// Minimum exponent for a fast path case, or `-⌊(SIG_BITS+1)/log2(5)⌋`
124+
const MIN_EXPONENT_FAST_PATH: i64 = -Self::MAX_EXPONENT_FAST_PATH;
125+
126+
/// Maximum exponent that can be represented for a disguised-fast path case.
127+
/// This is `MAX_EXPONENT_FAST_PATH + ⌊(SIG_BITS+1)/log2(10)⌋`
128+
const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 =
129+
Self::MAX_EXPONENT_FAST_PATH + (Self::SIG_TOTAL_BITS as f64 / f64::consts::LOG2_10) as i64;
130+
131+
/// Maximum mantissa for the fast-path (`1 << 53` for f64).
132+
const MAX_MANTISSA_FAST_PATH: u64 = 1 << Self::SIG_TOTAL_BITS;
133+
134+
/// Gets a small power-of-ten for fast-path multiplication.
135+
fn pow10_fast_path(exponent: usize) -> Self;
136+
137+
/// Converts integer into float through an as cast.
138+
/// This is only called in the fast-path algorithm, and therefore
139+
/// will not lose precision, since the value will always have
140+
/// only if the value is <= Self::MAX_MANTISSA_FAST_PATH.
141+
fn from_u64(v: u64) -> Self;
142+
}
143+
144+
#[cfg(target_has_reliable_f16)]
145+
impl Lemire for f16 {
146+
fn pow10_fast_path(exponent: usize) -> Self {
147+
#[allow(clippy::use_self)]
148+
const TABLE: [f16; 8] = [1e0, 1e1, 1e2, 1e3, 1e4, 0.0, 0.0, 0.];
149+
TABLE[exponent & 7]
150+
}
151+
152+
#[inline]
153+
fn from_u64(v: u64) -> Self {
154+
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
155+
v as _
156+
}
157+
}
158+
159+
impl Lemire for f32 {
160+
fn pow10_fast_path(exponent: usize) -> Self {
161+
#[allow(clippy::use_self)]
162+
const TABLE: [f32; 16] =
163+
[1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.];
164+
TABLE[exponent & 15]
165+
}
166+
167+
#[inline]
168+
fn from_u64(v: u64) -> Self {
169+
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
170+
v as _
171+
}
172+
}
173+
174+
impl Lemire for f64 {
175+
fn pow10_fast_path(exponent: usize) -> Self {
176+
const TABLE: [f64; 32] = [
177+
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
178+
1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0.,
179+
];
180+
TABLE[exponent & 31]
181+
}
182+
183+
#[inline]
184+
fn from_u64(v: u64) -> Self {
185+
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
186+
v as _
187+
}
188+
}
109189

110190
#[inline]
111191
pub(super) fn pfe_empty() -> ParseFloatError {

library/core/src/num/imp/dec2flt/parse.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
33
use dec2flt::common::{ByteSlice, is_8digits};
44
use dec2flt::decimal::Decimal;
5-
use dec2flt::float::Float;
65

7-
use crate::num::imp::dec2flt;
6+
use crate::num::imp::{Float, dec2flt};
87

98
const MIN_19DIGIT_INT: u64 = 100_0000_0000_0000_0000;
109

library/core/src/num/imp/dec2flt/slow.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
33
use dec2flt::common::BiasedFp;
44
use dec2flt::decimal_seq::{DecimalSeq, parse_decimal_seq};
5-
use dec2flt::float::Float;
65

7-
use crate::num::imp::dec2flt;
6+
use crate::num::imp::{Float, dec2flt};
87

98
/// Parse the significant digits and biased, binary exponent of a float.
109
///

library/core/src/num/imp/flt2dec/decoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Decodes a floating-point value into individual parts and error ranges.
22
33
use crate::num::FpCategory;
4-
use crate::num::imp::dec2flt::float::FloatExt;
4+
use crate::num::imp::FloatExt;
55

66
/// Decoded unsigned finite value, such that:
77
///

library/core/src/num/imp/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@ pub(crate) mod int_log10;
1616
pub(crate) mod int_sqrt;
1717
pub(crate) mod libm;
1818
pub(crate) mod overflow_panic;
19+
mod traits;
20+
21+
pub use traits::{Float, FloatExt, Int};
Lines changed: 15 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
//! Helper trait for generic float types.
1+
//! Numeric traits used for internal implementations.
22
3-
use core::f64;
3+
#![doc(hidden)]
4+
#![unstable(
5+
feature = "num_internals",
6+
reason = "internal routines only exposed for testing",
7+
issue = "none"
8+
)]
49

5-
use crate::fmt::{Debug, LowerExp};
610
use crate::num::FpCategory;
7-
use crate::ops::{self, Add, Div, Mul, Neg};
11+
use crate::{f64, fmt, ops};
812

913
/// Lossy `as` casting between two types.
1014
pub trait CastInto<T: Copy>: Copy {
@@ -16,7 +20,7 @@ pub trait Int:
1620
Sized
1721
+ Clone
1822
+ Copy
19-
+ Debug
23+
+ fmt::Debug
2024
+ ops::Shr<u32, Output = Self>
2125
+ ops::Shl<u32, Output = Self>
2226
+ ops::BitAnd<Output = Self>
@@ -51,17 +55,17 @@ int!(u16, u32, u64);
5155
#[doc(hidden)]
5256
pub trait Float:
5357
Sized
54-
+ Div<Output = Self>
55-
+ Neg<Output = Self>
56-
+ Mul<Output = Self>
57-
+ Add<Output = Self>
58-
+ LowerExp
58+
+ ops::Div<Output = Self>
59+
+ ops::Neg<Output = Self>
60+
+ ops::Mul<Output = Self>
61+
+ ops::Add<Output = Self>
62+
+ fmt::Debug
63+
+ fmt::LowerExp
5964
+ PartialEq
6065
+ PartialOrd
6166
+ Default
6267
+ Clone
6368
+ Copy
64-
+ Debug
6569
{
6670
/// The unsigned integer with the same size as the float
6771
type Int: Int + Into<u64>;
@@ -184,41 +188,6 @@ pub trait FloatExt: Float {
184188
}
185189
}
186190

187-
/// Extension to `Float` that are necessary for parsing using the Lemire method.
188-
///
189-
/// See the parent module's doc comment for why this is necessary.
190-
///
191-
/// Not intended for use outside of the `dec2flt` module.
192-
#[doc(hidden)]
193-
pub trait Lemire: FloatExt {
194-
/// Maximum exponent for a fast path case, or `⌊(SIG_BITS+1)/log2(5)⌋`
195-
// assuming FLT_EVAL_METHOD = 0
196-
const MAX_EXPONENT_FAST_PATH: i64 = {
197-
let log2_5 = f64::consts::LOG2_10 - 1.0;
198-
(Self::SIG_TOTAL_BITS as f64 / log2_5) as i64
199-
};
200-
201-
/// Minimum exponent for a fast path case, or `-⌊(SIG_BITS+1)/log2(5)⌋`
202-
const MIN_EXPONENT_FAST_PATH: i64 = -Self::MAX_EXPONENT_FAST_PATH;
203-
204-
/// Maximum exponent that can be represented for a disguised-fast path case.
205-
/// This is `MAX_EXPONENT_FAST_PATH + ⌊(SIG_BITS+1)/log2(10)⌋`
206-
const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 =
207-
Self::MAX_EXPONENT_FAST_PATH + (Self::SIG_TOTAL_BITS as f64 / f64::consts::LOG2_10) as i64;
208-
209-
/// Maximum mantissa for the fast-path (`1 << 53` for f64).
210-
const MAX_MANTISSA_FAST_PATH: u64 = 1 << Self::SIG_TOTAL_BITS;
211-
212-
/// Gets a small power-of-ten for fast-path multiplication.
213-
fn pow10_fast_path(exponent: usize) -> Self;
214-
215-
/// Converts integer into float through an as cast.
216-
/// This is only called in the fast-path algorithm, and therefore
217-
/// will not lose precision, since the value will always have
218-
/// only if the value is <= Self::MAX_MANTISSA_FAST_PATH.
219-
fn from_u64(v: u64) -> Self;
220-
}
221-
222191
/// Solve for `b` in `10^b = 2^a`
223192
const fn pow2_to_pow10(a: i64) -> i64 {
224193
let res = (a as f64) / f64::consts::LOG2_10;
@@ -260,21 +229,6 @@ impl FloatExt for f16 {
260229
}
261230
}
262231

263-
#[cfg(target_has_reliable_f16)]
264-
impl Lemire for f16 {
265-
fn pow10_fast_path(exponent: usize) -> Self {
266-
#[allow(clippy::use_self)]
267-
const TABLE: [f16; 8] = [1e0, 1e1, 1e2, 1e3, 1e4, 0.0, 0.0, 0.];
268-
TABLE[exponent & 7]
269-
}
270-
271-
#[inline]
272-
fn from_u64(v: u64) -> Self {
273-
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
274-
v as _
275-
}
276-
}
277-
278232
impl Float for f32 {
279233
type Int = u32;
280234

@@ -308,21 +262,6 @@ impl FloatExt for f32 {
308262
}
309263
}
310264

311-
impl Lemire for f32 {
312-
fn pow10_fast_path(exponent: usize) -> Self {
313-
#[allow(clippy::use_self)]
314-
const TABLE: [f32; 16] =
315-
[1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.];
316-
TABLE[exponent & 15]
317-
}
318-
319-
#[inline]
320-
fn from_u64(v: u64) -> Self {
321-
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
322-
v as _
323-
}
324-
}
325-
326265
impl Float for f64 {
327266
type Int = u64;
328267

@@ -355,19 +294,3 @@ impl FloatExt for f64 {
355294
f64::from_bits(v)
356295
}
357296
}
358-
359-
impl Lemire for f64 {
360-
fn pow10_fast_path(exponent: usize) -> Self {
361-
const TABLE: [f64; 32] = [
362-
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
363-
1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0.,
364-
];
365-
TABLE[exponent & 31]
366-
}
367-
368-
#[inline]
369-
fn from_u64(v: u64) -> Self {
370-
debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
371-
v as _
372-
}
373-
}

library/coretests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
#![feature(next_index)]
9393
#![feature(non_exhaustive_omitted_patterns_lint)]
9494
#![feature(nonzero_from_str_radix)]
95+
#![feature(num_internals)]
9596
#![feature(numfmt)]
9697
#![feature(one_sided_range)]
9798
#![feature(option_reduce)]

0 commit comments

Comments
 (0)