diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/ryu/src/pretty | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/ryu/src/pretty')
-rw-r--r-- | third_party/rust/ryu/src/pretty/exponent.rs | 49 | ||||
-rw-r--r-- | third_party/rust/ryu/src/pretty/mantissa.rs | 51 | ||||
-rw-r--r-- | third_party/rust/ryu/src/pretty/mod.rs | 228 |
3 files changed, 328 insertions, 0 deletions
diff --git a/third_party/rust/ryu/src/pretty/exponent.rs b/third_party/rust/ryu/src/pretty/exponent.rs new file mode 100644 index 0000000000..f10643f22d --- /dev/null +++ b/third_party/rust/ryu/src/pretty/exponent.rs @@ -0,0 +1,49 @@ +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 { + *result = b'-'; + result = result.offset(1); + k = -k; + } + + debug_assert!(k < 1000); + if k >= 100 { + *result = b'0' + (k / 100) as u8; + k %= 100; + let d = DIGIT_TABLE.get_unchecked(k as usize * 2); + ptr::copy_nonoverlapping(d, result.offset(1), 2); + sign as usize + 3 + } else if k >= 10 { + let d = DIGIT_TABLE.get_unchecked(k as usize * 2); + ptr::copy_nonoverlapping(d, result, 2); + sign as usize + 2 + } else { + *result = b'0' + k as u8; + sign as usize + 1 + } +} + +#[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 { + *result = b'-'; + result = result.offset(1); + k = -k; + } + + debug_assert!(k < 100); + if k >= 10 { + let d = DIGIT_TABLE.get_unchecked(k as usize * 2); + ptr::copy_nonoverlapping(d, result, 2); + sign as usize + 2 + } else { + *result = b'0' + k as u8; + sign as usize + 1 + } +} diff --git a/third_party/rust/ryu/src/pretty/mantissa.rs b/third_party/rust/ryu/src/pretty/mantissa.rs new file mode 100644 index 0000000000..428023233d --- /dev/null +++ b/third_party/rust/ryu/src/pretty/mantissa.rs @@ -0,0 +1,51 @@ +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. + let mut output2 = (output - 100_000_000 * (output / 100_000_000)) as u32; + output /= 100_000_000; + + let c = output2 % 10_000; + output2 /= 10_000; + let d = output2 % 10_000; + let c0 = (c % 100) << 1; + let c1 = (c / 100) << 1; + let d0 = (d % 100) << 1; + let d1 = (d / 100) << 1; + ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c0 as usize), result.offset(-2), 2); + ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c1 as usize), result.offset(-4), 2); + ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(d0 as usize), result.offset(-6), 2); + ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(d1 as usize), result.offset(-8), 2); + result = result.offset(-8); + } + 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; + output /= 10_000; + let c0 = (c % 100) << 1; + let c1 = (c / 100) << 1; + ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c0 as usize), result.offset(-2), 2); + ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c1 as usize), result.offset(-4), 2); + result = result.offset(-4); + } + if output >= 100 { + let c = ((output % 100) << 1) as u32; + output /= 100; + ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c as usize), result.offset(-2), 2); + result = result.offset(-2); + } + if output >= 10 { + let c = (output << 1) as u32; + ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c as usize), result.offset(-2), 2); + } else { + *result.offset(-1) = b'0' + output as u8; + } +} diff --git a/third_party/rust/ryu/src/pretty/mod.rs b/third_party/rust/ryu/src/pretty/mod.rs new file mode 100644 index 0000000000..3dead1bf36 --- /dev/null +++ b/third_party/rust/ryu/src/pretty/mod.rs @@ -0,0 +1,228 @@ +mod exponent; +mod mantissa; + +use core::{mem, ptr}; + +use self::exponent::*; +use self::mantissa::*; +use common; +use d2s; +use d2s::*; +use f2s::*; + +#[cfg(feature = "no-panic")] +use no_panic::no_panic; + +/// Print f64 to the given buffer and return number of bytes written. +/// +/// At most 24 bytes will be written. +/// +/// ## Special cases +/// +/// This function **does not** check for NaN or infinity. If the input +/// number is not a finite float, the printed representation will be some +/// correctly formatted but unspecified numerical value. +/// +/// Please check [`is_finite`] yourself before calling this function, or +/// check [`is_nan`] and [`is_infinite`] and handle those cases yourself. +/// +/// [`is_finite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_finite +/// [`is_nan`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_nan +/// [`is_infinite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_infinite +/// +/// ## Safety +/// +/// The `result` pointer argument must point to sufficiently many writable bytes +/// to hold Ryū's representation of `f`. +/// +/// ## Example +/// +/// ```edition2018 +/// use std::mem::MaybeUninit; +/// +/// let f = 1.234f64; +/// +/// unsafe { +/// let mut buffer: [MaybeUninit<u8>; 24] = MaybeUninit::uninit().assume_init(); +/// let len = ryu::raw::format64(f, buffer.as_mut_ptr() as *mut u8); +/// let slice = std::slice::from_raw_parts(buffer.as_ptr() as *const u8, len); +/// let print = std::str::from_utf8_unchecked(slice); +/// assert_eq!(print, "1.234"); +/// } +/// ``` +#[cfg_attr(must_use_return, must_use)] +#[cfg_attr(feature = "no-panic", no_panic)] +pub unsafe fn format64(f: f64, result: *mut u8) -> usize { + let bits = mem::transmute::<f64, u64>(f); + let sign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0; + let ieee_mantissa = bits & ((1u64 << DOUBLE_MANTISSA_BITS) - 1); + let ieee_exponent = + (bits >> DOUBLE_MANTISSA_BITS) as u32 & ((1u32 << DOUBLE_EXPONENT_BITS) - 1); + + let mut index = 0isize; + if sign { + *result = b'-'; + index += 1; + } + + if ieee_exponent == 0 && ieee_mantissa == 0 { + ptr::copy_nonoverlapping(b"0.0".as_ptr(), result.offset(index), 3); + return sign as usize + 3; + } + + let v = d2d(ieee_mantissa, ieee_exponent); + + let length = d2s::decimal_length17(v.mantissa) as isize; + let k = v.exponent as isize; + let kk = length + k; // 10^(kk-1) <= v < 10^kk + debug_assert!(k >= -324); + + if 0 <= k && kk <= 16 { + // 1234e7 -> 12340000000.0 + write_mantissa_long(v.mantissa, result.offset(index + length)); + for i in length..kk { + *result.offset(index + i) = b'0'; + } + *result.offset(index + kk) = b'.'; + *result.offset(index + kk + 1) = b'0'; + index as usize + kk as usize + 2 + } else if 0 < kk && kk <= 16 { + // 1234e-2 -> 12.34 + write_mantissa_long(v.mantissa, result.offset(index + length + 1)); + ptr::copy(result.offset(index + 1), result.offset(index), kk as usize); + *result.offset(index + kk) = b'.'; + index as usize + length as usize + 1 + } else if -5 < kk && kk <= 0 { + // 1234e-6 -> 0.001234 + *result.offset(index) = b'0'; + *result.offset(index + 1) = b'.'; + let offset = 2 - kk; + for i in 2..offset { + *result.offset(index + i) = b'0'; + } + write_mantissa_long(v.mantissa, result.offset(index + length + offset)); + index as usize + length as usize + offset as usize + } else if length == 1 { + // 1e30 + *result.offset(index) = b'0' + v.mantissa as u8; + *result.offset(index + 1) = b'e'; + index as usize + 2 + write_exponent3(kk - 1, result.offset(index + 2)) + } else { + // 1234e30 -> 1.234e33 + write_mantissa_long(v.mantissa, result.offset(index + length + 1)); + *result.offset(index) = *result.offset(index + 1); + *result.offset(index + 1) = b'.'; + *result.offset(index + length + 1) = b'e'; + index as usize + + length as usize + + 2 + + write_exponent3(kk - 1, result.offset(index + length + 2)) + } +} + +/// Print f32 to the given buffer and return number of bytes written. +/// +/// At most 16 bytes will be written. +/// +/// ## Special cases +/// +/// This function **does not** check for NaN or infinity. If the input +/// number is not a finite float, the printed representation will be some +/// correctly formatted but unspecified numerical value. +/// +/// Please check [`is_finite`] yourself before calling this function, or +/// check [`is_nan`] and [`is_infinite`] and handle those cases yourself. +/// +/// [`is_finite`]: https://doc.rust-lang.org/std/primitive.f32.html#method.is_finite +/// [`is_nan`]: https://doc.rust-lang.org/std/primitive.f32.html#method.is_nan +/// [`is_infinite`]: https://doc.rust-lang.org/std/primitive.f32.html#method.is_infinite +/// +/// ## Safety +/// +/// The `result` pointer argument must point to sufficiently many writable bytes +/// to hold Ryū's representation of `f`. +/// +/// ## Example +/// +/// ```edition2018 +/// use std::mem::MaybeUninit; +/// +/// let f = 1.234f32; +/// +/// unsafe { +/// let mut buffer: [MaybeUninit<u8>; 16] = MaybeUninit::uninit().assume_init(); +/// let len = ryu::raw::format32(f, buffer.as_mut_ptr() as *mut u8); +/// let slice = std::slice::from_raw_parts(buffer.as_ptr() as *const u8, len); +/// let print = std::str::from_utf8_unchecked(slice); +/// assert_eq!(print, "1.234"); +/// } +/// ``` +#[cfg_attr(must_use_return, must_use)] +#[cfg_attr(feature = "no-panic", no_panic)] +pub unsafe fn format32(f: f32, result: *mut u8) -> usize { + let bits = mem::transmute::<f32, u32>(f); + let sign = ((bits >> (FLOAT_MANTISSA_BITS + FLOAT_EXPONENT_BITS)) & 1) != 0; + let ieee_mantissa = bits & ((1u32 << FLOAT_MANTISSA_BITS) - 1); + let ieee_exponent = + ((bits >> FLOAT_MANTISSA_BITS) & ((1u32 << FLOAT_EXPONENT_BITS) - 1)) as u32; + + let mut index = 0isize; + if sign { + *result = b'-'; + index += 1; + } + + if ieee_exponent == 0 && ieee_mantissa == 0 { + ptr::copy_nonoverlapping(b"0.0".as_ptr(), result.offset(index), 3); + return sign as usize + 3; + } + + let v = f2d(ieee_mantissa, ieee_exponent); + + let length = common::decimal_length9(v.mantissa) as isize; + let k = v.exponent as isize; + let kk = length + k; // 10^(kk-1) <= v < 10^kk + debug_assert!(k >= -45); + + if 0 <= k && kk <= 13 { + // 1234e7 -> 12340000000.0 + write_mantissa(v.mantissa, result.offset(index + length)); + for i in length..kk { + *result.offset(index + i) = b'0'; + } + *result.offset(index + kk) = b'.'; + *result.offset(index + kk + 1) = b'0'; + index as usize + kk as usize + 2 + } else if 0 < kk && kk <= 13 { + // 1234e-2 -> 12.34 + write_mantissa(v.mantissa, result.offset(index + length + 1)); + ptr::copy(result.offset(index + 1), result.offset(index), kk as usize); + *result.offset(index + kk) = b'.'; + index as usize + length as usize + 1 + } else if -6 < kk && kk <= 0 { + // 1234e-6 -> 0.001234 + *result.offset(index) = b'0'; + *result.offset(index + 1) = b'.'; + let offset = 2 - kk; + for i in 2..offset { + *result.offset(index + i) = b'0'; + } + write_mantissa(v.mantissa, result.offset(index + length + offset)); + index as usize + length as usize + offset as usize + } else if length == 1 { + // 1e30 + *result.offset(index) = b'0' + v.mantissa as u8; + *result.offset(index + 1) = b'e'; + index as usize + 2 + write_exponent2(kk - 1, result.offset(index + 2)) + } else { + // 1234e30 -> 1.234e33 + write_mantissa(v.mantissa, result.offset(index + length + 1)); + *result.offset(index) = *result.offset(index + 1); + *result.offset(index + 1) = b'.'; + *result.offset(index + length + 1) = b'e'; + index as usize + + length as usize + + 2 + + write_exponent2(kk - 1, result.offset(index + length + 2)) + } +} |