mirror of
https://github.com/openharmony/third_party_rust_ryu.git
synced 2026-07-19 19:13:31 -04:00
More functions that can never panic
This commit is contained in:
@@ -2,6 +2,9 @@ use core::{mem, str};
|
||||
|
||||
use pretty;
|
||||
|
||||
#[cfg(feature = "no-panic")]
|
||||
use no_panic::no_panic;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Buffer {
|
||||
bytes: [u8; 24],
|
||||
@@ -9,12 +12,14 @@ pub struct Buffer {
|
||||
|
||||
impl Buffer {
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||
pub fn new() -> Self {
|
||||
Buffer {
|
||||
bytes: unsafe { mem::uninitialized() },
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||
pub fn format<F: Float>(&mut self, f: F) -> &str {
|
||||
f.write_to_ryu_buffer(self)
|
||||
}
|
||||
@@ -22,6 +27,7 @@ impl Buffer {
|
||||
|
||||
impl Default for Buffer {
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||
fn default() -> Self {
|
||||
Buffer::new()
|
||||
}
|
||||
@@ -34,6 +40,7 @@ pub trait Float: Sealed {
|
||||
|
||||
impl Float for f32 {
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||
fn write_to_ryu_buffer(self, buffer: &mut Buffer) -> &str {
|
||||
unsafe {
|
||||
let n = pretty::f2s_buffered_n(self, &mut buffer.bytes[0]);
|
||||
@@ -46,6 +53,7 @@ impl Float for f32 {
|
||||
|
||||
impl Float for f64 {
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||
fn write_to_ryu_buffer(self, buffer: &mut Buffer) -> &str {
|
||||
unsafe {
|
||||
let n = pretty::d2s_buffered_n(self, &mut buffer.bytes[0]);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
use core::ptr;
|
||||
|
||||
// Returns e == 0 ? 1 : ceil(log_2(5^e)).
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub fn pow5bits(e: i32) -> u32 {
|
||||
// This approximation works up to the point that the multiplication overflows at e = 3529.
|
||||
// If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater
|
||||
@@ -31,6 +32,7 @@ pub fn pow5bits(e: i32) -> u32 {
|
||||
}
|
||||
|
||||
// Returns floor(log_10(2^e)).
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub fn log10_pow2(e: i32) -> i32 {
|
||||
// The first value this approximation fails for is 2^1651 which is just greater than 10^297.
|
||||
debug_assert!(e >= 0);
|
||||
@@ -39,6 +41,7 @@ pub fn log10_pow2(e: i32) -> i32 {
|
||||
}
|
||||
|
||||
// Returns floor(log_10(5^e)).
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub fn log10_pow5(e: i32) -> i32 {
|
||||
// The first value this approximation fails for is 5^2621 which is just greater than 10^1832.
|
||||
debug_assert!(e >= 0);
|
||||
@@ -46,6 +49,7 @@ pub fn log10_pow5(e: i32) -> i32 {
|
||||
((e as u32 * 732923) >> 20) as i32
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub unsafe fn copy_special_str(result: *mut u8, sign: bool) -> usize {
|
||||
if sign {
|
||||
ptr::write(result, b'-');
|
||||
|
||||
@@ -33,6 +33,7 @@ pub const DOUBLE_EXPONENT_BITS: u32 = 11;
|
||||
const DOUBLE_POW5_INV_BITCOUNT: i32 = 122;
|
||||
const DOUBLE_POW5_BITCOUNT: i32 = 121;
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
fn pow5_factor(mut value: u64) -> i32 {
|
||||
let mut count = 0i32;
|
||||
loop {
|
||||
@@ -48,23 +49,27 @@ fn pow5_factor(mut value: u64) -> i32 {
|
||||
}
|
||||
|
||||
// Returns true if value is divisible by 5^p.
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
fn multiple_of_power_of_5(value: u64, p: u32) -> bool {
|
||||
// I tried a case distinction on p, but there was no performance difference.
|
||||
pow5_factor(value) >= p as i32
|
||||
}
|
||||
|
||||
// Returns true if value is divisible by 2^p.
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
fn multiple_of_power_of_2(value: u64, p: u32) -> bool {
|
||||
// return __builtin_ctz(value) >= p;
|
||||
(value & ((1u64 << (p - 1)) - 1)) == 0
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
fn mul_shift(m: u64, mul: &(u64, u64), j: u32) -> u64 {
|
||||
let b0 = m as u128 * mul.0 as u128;
|
||||
let b2 = m as u128 * mul.1 as u128;
|
||||
(((b0 >> 64) + b2) >> (j - 64)) as u64
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
fn mul_shift_all(
|
||||
m: u64,
|
||||
mul: &(u64, u64),
|
||||
@@ -78,6 +83,7 @@ fn mul_shift_all(
|
||||
mul_shift(4 * m, mul, j)
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub fn decimal_length(v: u64) -> u32 {
|
||||
// This is slightly faster than a loop.
|
||||
// The average output length is 16.38 digits, so we check high-to-low.
|
||||
@@ -128,6 +134,7 @@ pub struct FloatingDecimal64 {
|
||||
pub exponent: i32,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
|
||||
let bias = (1u32 << (DOUBLE_EXPONENT_BITS - 1)) - 1;
|
||||
|
||||
@@ -279,6 +286,7 @@ pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
unsafe fn to_chars(v: FloatingDecimal64, sign: bool, result: *mut u8) -> usize {
|
||||
// Step 5: Print the decimal representation.
|
||||
let mut index = 0isize;
|
||||
|
||||
@@ -117,6 +117,7 @@ static FLOAT_POW5_SPLIT: [u64; 47] = [
|
||||
2019483917365790221,
|
||||
];
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
fn pow5_factor(mut value: u32) -> i32 {
|
||||
let mut count = 0i32;
|
||||
loop {
|
||||
@@ -132,12 +133,14 @@ fn pow5_factor(mut value: u32) -> i32 {
|
||||
}
|
||||
|
||||
// Returns true if value is divisible by 5^p.
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
fn multiple_of_power_of_5(value: u32, p: i32) -> bool {
|
||||
pow5_factor(value) >= p
|
||||
}
|
||||
|
||||
// It seems to be slightly faster to avoid uint128_t here, although the
|
||||
// generated code for uint128_t looks slightly nicer.
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
fn mul_shift(m: u32, factor: u64, shift: i32) -> u32 {
|
||||
debug_assert!(shift > 32);
|
||||
|
||||
@@ -154,16 +157,19 @@ fn mul_shift(m: u32, factor: u64, shift: i32) -> u32 {
|
||||
shifted_sum as u32
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
fn mul_pow5_inv_div_pow2(m: u32, q: u32, j: i32) -> u32 {
|
||||
debug_assert!(q < FLOAT_POW5_INV_SPLIT.len() as u32);
|
||||
unsafe { mul_shift(m, *FLOAT_POW5_INV_SPLIT.get_unchecked(q as usize), j) }
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
fn mul_pow5_div_pow2(m: u32, i: u32, j: i32) -> u32 {
|
||||
debug_assert!(i < FLOAT_POW5_SPLIT.len() as u32);
|
||||
unsafe { mul_shift(m, *FLOAT_POW5_SPLIT.get_unchecked(i as usize), j) }
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub fn decimal_length(v: u32) -> u32 {
|
||||
// Function precondition: v is not a 10-digit number.
|
||||
// (9 digits are sufficient for round-tripping.)
|
||||
@@ -196,6 +202,7 @@ pub struct FloatingDecimal32 {
|
||||
pub exponent: i32,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub fn f2d(ieee_mantissa: u32, ieee_exponent: u32) -> FloatingDecimal32 {
|
||||
let bias = (1u32 << (FLOAT_EXPONENT_BITS - 1)) - 1;
|
||||
|
||||
@@ -330,6 +337,7 @@ pub fn f2d(ieee_mantissa: u32, ieee_exponent: u32) -> FloatingDecimal32 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
unsafe fn to_chars(v: FloatingDecimal32, sign: bool, result: *mut u8) -> usize {
|
||||
// Step 5: Print the decimal representation.
|
||||
let mut index = 0isize;
|
||||
|
||||
@@ -2,6 +2,7 @@ use core::ptr;
|
||||
|
||||
use digit_table::*;
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub unsafe fn write_exponent3(mut k: isize, mut result: *mut u8) -> usize {
|
||||
let sign = k < 0;
|
||||
if sign {
|
||||
@@ -26,6 +27,7 @@ pub unsafe fn write_exponent3(mut k: isize, mut result: *mut u8) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub unsafe fn write_exponent2(mut k: isize, mut result: *mut u8) -> usize {
|
||||
let sign = k < 0;
|
||||
if sign {
|
||||
|
||||
@@ -2,6 +2,7 @@ use core::ptr;
|
||||
|
||||
use digit_table::*;
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub unsafe fn write_mantissa_long(mut output: u64, mut result: *mut u8) {
|
||||
if (output >> 32) != 0 {
|
||||
// One expensive 64-bit division.
|
||||
@@ -24,6 +25,7 @@ pub unsafe fn write_mantissa_long(mut output: u64, mut result: *mut u8) {
|
||||
write_mantissa(output as u32, result);
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub unsafe fn write_mantissa(mut output: u32, mut result: *mut u8) {
|
||||
while output >= 10_000 {
|
||||
let c = (output - 10_000 * (output / 10_000)) as u32;
|
||||
|
||||
@@ -8,7 +8,11 @@ use self::mantissa::*;
|
||||
use d2s::{self, *};
|
||||
use f2s::{self, *};
|
||||
|
||||
#[cfg(feature = "no-panic")]
|
||||
use no_panic::no_panic;
|
||||
|
||||
#[must_use]
|
||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||
pub unsafe fn d2s_buffered_n(f: f64, result: *mut u8) -> usize {
|
||||
let bits = f.to_bits().to_le();
|
||||
let sign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
|
||||
@@ -80,6 +84,7 @@ pub unsafe fn d2s_buffered_n(f: f64, result: *mut u8) -> usize {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||
pub unsafe fn f2s_buffered_n(f: f32, result: *mut u8) -> usize {
|
||||
let bits = f.to_bits().to_le();
|
||||
let sign = ((bits >> (FLOAT_MANTISSA_BITS + FLOAT_EXPONENT_BITS)) & 1) != 0;
|
||||
|
||||
Reference in New Issue
Block a user