mirror of
https://github.com/openharmony/third_party_rust_ryu.git
synced 2026-07-19 19:13:31 -04:00
Merge pull request #15 from dtolnay/cases
Split format and format_finite
This commit is contained in:
+1
-1
@@ -18,7 +18,7 @@ macro_rules! benches {
|
||||
|
||||
b.iter(move || {
|
||||
let value = black_box($value);
|
||||
let formatted = buf.format(value);
|
||||
let formatted = buf.format_finite(value);
|
||||
black_box(formatted);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ macro_rules! benchmark {
|
||||
|
||||
let t1 = std::time::SystemTime::now();
|
||||
for _ in 0..ITERATIONS {
|
||||
throwaway += ryu::Buffer::new().format(f).len();
|
||||
throwaway += ryu::Buffer::new().format_finite(f).len();
|
||||
}
|
||||
let duration = t1.elapsed().unwrap();
|
||||
let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
|
||||
|
||||
+74
-5
@@ -5,13 +5,17 @@ use raw;
|
||||
#[cfg(feature = "no-panic")]
|
||||
use no_panic::no_panic;
|
||||
|
||||
const NAN: &'static str = "NaN";
|
||||
const INFINITY: &'static str = "inf";
|
||||
const NEG_INFINITY: &'static str = "-inf";
|
||||
|
||||
/// Safe API for formatting floating point numbers to text.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```edition2018
|
||||
/// let mut buffer = ryu::Buffer::new();
|
||||
/// let printed = buffer.format(1.234);
|
||||
/// let printed = buffer.format_finite(1.234);
|
||||
/// assert_eq!(printed, "1.234");
|
||||
/// ```
|
||||
#[derive(Copy, Clone)]
|
||||
@@ -30,6 +34,27 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Print a floating point number into this buffer and return a reference to
|
||||
/// its string representation within the buffer.
|
||||
///
|
||||
/// # Special cases
|
||||
///
|
||||
/// This function formats NaN as the string "NaN", positive infinity as
|
||||
/// "inf", and negative infinity as "-inf" to match std::fmt.
|
||||
///
|
||||
/// If your input is known to be finite, you may get better performance by
|
||||
/// calling the `format_finite` method instead of `format` to avoid the
|
||||
/// checks for special cases.
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||
pub fn format<F: Float>(&mut self, f: F) -> &str {
|
||||
if f.is_nonfinite() {
|
||||
f.format_nonfinite()
|
||||
} else {
|
||||
self.format_finite(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Print a floating point number into this buffer and return a reference to
|
||||
/// its string representation within the buffer.
|
||||
///
|
||||
@@ -47,7 +72,7 @@ impl Buffer {
|
||||
/// [`is_infinite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_infinite
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||
pub fn format<F: Float>(&mut self, f: F) -> &str {
|
||||
pub fn format_finite<F: Float>(&mut self, f: F) -> &str {
|
||||
unsafe {
|
||||
let n = f.write_to_ryu_buffer(&mut self.bytes[0]);
|
||||
debug_assert!(n <= self.bytes.len());
|
||||
@@ -74,13 +99,36 @@ pub trait Float: Sealed {}
|
||||
impl Float for f32 {}
|
||||
impl Float for f64 {}
|
||||
|
||||
pub trait Sealed {
|
||||
pub trait Sealed: Copy {
|
||||
fn is_nonfinite(self) -> bool;
|
||||
fn format_nonfinite(self) -> &'static str;
|
||||
unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize;
|
||||
}
|
||||
|
||||
impl Sealed for f32 {
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||
fn is_nonfinite(self) -> bool {
|
||||
const EXP_MASK: u32 = 0x7f800000;
|
||||
let bits = unsafe { mem::transmute::<f32, u32>(self) };
|
||||
bits & EXP_MASK == EXP_MASK
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
fn format_nonfinite(self) -> &'static str {
|
||||
const MANTISSA_MASK: u32 = 0x007fffff;
|
||||
const SIGN_MASK: u32 = 0x80000000;
|
||||
let bits = unsafe { mem::transmute::<f32, u32>(self) };
|
||||
if bits & MANTISSA_MASK != 0 {
|
||||
NAN
|
||||
} else if bits & SIGN_MASK != 0 {
|
||||
NEG_INFINITY
|
||||
} else {
|
||||
INFINITY
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
|
||||
raw::format32(self, result)
|
||||
}
|
||||
@@ -88,7 +136,28 @@ impl Sealed for f32 {
|
||||
|
||||
impl Sealed for f64 {
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||
fn is_nonfinite(self) -> bool {
|
||||
const EXP_MASK: u64 = 0x7ff0000000000000;
|
||||
let bits = unsafe { mem::transmute::<f64, u64>(self) };
|
||||
bits & EXP_MASK == EXP_MASK
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
fn format_nonfinite(self) -> &'static str {
|
||||
const MANTISSA_MASK: u64 = 0x000fffffffffffff;
|
||||
const SIGN_MASK: u64 = 0x8000000000000000;
|
||||
let bits = unsafe { mem::transmute::<f64, u64>(self) };
|
||||
if bits & MANTISSA_MASK != 0 {
|
||||
NAN
|
||||
} else if bits & SIGN_MASK != 0 {
|
||||
NEG_INFINITY
|
||||
} else {
|
||||
INFINITY
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
|
||||
raw::format64(self, result)
|
||||
}
|
||||
|
||||
@@ -27,9 +27,6 @@ use d2s_intrinsics::*;
|
||||
#[cfg(feature = "small")]
|
||||
use d2s_small_table::*;
|
||||
|
||||
#[cfg(feature = "no-panic")]
|
||||
use no_panic::no_panic;
|
||||
|
||||
pub const DOUBLE_MANTISSA_BITS: u32 = 52;
|
||||
pub const DOUBLE_EXPONENT_BITS: u32 = 11;
|
||||
|
||||
|
||||
@@ -20,9 +20,6 @@
|
||||
|
||||
use common::*;
|
||||
|
||||
#[cfg(feature = "no-panic")]
|
||||
use no_panic::no_panic;
|
||||
|
||||
pub const FLOAT_MANTISSA_BITS: u32 = 23;
|
||||
pub const FLOAT_EXPONENT_BITS: u32 = 8;
|
||||
|
||||
|
||||
+5
-2
@@ -54,7 +54,7 @@ fn test_random() {
|
||||
let mut buffer = ryu::Buffer::new();
|
||||
for _ in 0..1000000 {
|
||||
let f: f64 = rand::random();
|
||||
assert_eq!(f, buffer.format(f).parse().unwrap());
|
||||
assert_eq!(f, buffer.format_finite(f).parse().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ fn test_non_finite() {
|
||||
for i in 0u64..1 << 23 {
|
||||
let f = f64::from_bits((((1 << 11) - 1) << 52) + (i << 29));
|
||||
assert!(!f.is_finite(), "f={}", f);
|
||||
ryu::Buffer::new().format(f);
|
||||
ryu::Buffer::new().format_finite(f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,9 @@ fn test_basic() {
|
||||
check!(-0.0);
|
||||
check!(1.0);
|
||||
check!(-1.0);
|
||||
assert_eq!(pretty(f64::NAN), "NaN");
|
||||
assert_eq!(pretty(f64::INFINITY), "inf");
|
||||
assert_eq!(pretty(f64::NEG_INFINITY), "-inf");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ fn test_exhaustive() {
|
||||
}
|
||||
let n = unsafe { ryu::raw::format32(f, &mut bytes[0]) };
|
||||
assert_eq!(Ok(Ok(f)), str::from_utf8(&bytes[..n]).map(str::parse));
|
||||
assert_eq!(Ok(f), buffer.format(f).parse());
|
||||
assert_eq!(Ok(f), buffer.format_finite(f).parse());
|
||||
}
|
||||
|
||||
let increment = (max - min + 1) as usize;
|
||||
|
||||
+5
-2
@@ -49,7 +49,7 @@ fn test_random() {
|
||||
let mut buffer = ryu::Buffer::new();
|
||||
for _ in 0..1000000 {
|
||||
let f: f32 = rand::random();
|
||||
assert_eq!(f, buffer.format(f).parse().unwrap());
|
||||
assert_eq!(f, buffer.format_finite(f).parse().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ fn test_non_finite() {
|
||||
for i in 0u32..1 << 23 {
|
||||
let f = f32::from_bits((((1 << 8) - 1) << 23) + i);
|
||||
assert!(!f.is_finite(), "f={}", f);
|
||||
ryu::Buffer::new().format(f);
|
||||
ryu::Buffer::new().format_finite(f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,9 @@ fn test_basic() {
|
||||
check!(-0.0);
|
||||
check!(1.0);
|
||||
check!(-1.0);
|
||||
assert_eq!(pretty(f32::NAN), "NaN");
|
||||
assert_eq!(pretty(f32::INFINITY), "inf");
|
||||
assert_eq!(pretty(f32::NEG_INFINITY), "-inf");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user