Skip to content

Commit

Permalink
Sync to upstream/master
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat committed Mar 1, 2024
1 parent 728e7a2 commit 3bd7789
Show file tree
Hide file tree
Showing 21 changed files with 161 additions and 33 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ permissions:
env:
RUSTFLAGS: -Dwarnings

permissions:
contents: read

env:
RUSTFLAGS: -Dwarnings

jobs:
test:
name: Rust ${{matrix.rust}}
Expand Down Expand Up @@ -50,13 +56,26 @@ jobs:
- run: cargo build
- run: cargo build --features small

doc:
name: Documentation
runs-on: ubuntu-latest
timeout-minutes: 45
env:
RUSTDOCFLAGS: -Dwarnings
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- uses: dtolnay/install@cargo-docs-rs
- run: cargo docs-rs

miri:
name: Miri
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@miri
- run: cargo miri setup
- run: cargo miri test
env:
MIRIFLAGS: -Zmiri-strict-provenance
Expand Down
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "ryu-js"
version = "1.0.0"
authors = ["David Tolnay <dtolnay@gmail.com>", "boa-dev"]
categories = ["value-formatting", "no-std"]
categories = ["value-formatting", "no-std", "no-std::no-alloc"]
description = "Fast floating point to string conversion, ECMAScript compliant."
documentation = "https://docs.rs/ryu-js"
edition = "2018"
Expand Down Expand Up @@ -35,6 +35,9 @@ doc-scrape-examples = false
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

# See: https://github.com/rust-lang/rust/pull/84176
rustdoc-args = ["--generate-link-to-definition"]

[[bench]]
name = "bench"
harness = false
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ under the creative commons CC-BY-SA license.
This Rust implementation is a line-by-line port of Ulf Adams' implementation in
C, [https://github.com/ulfjack/ryu][upstream].

*Requirements: this crate supports any compiler version back to rustc 1.64; it
*Requirements: This crate supports any compiler version back to rustc 1.64; it
uses nothing from the Rust standard library so is usable from no_std crates.*

[paper]: https://dl.acm.org/citation.cfm?id=3192369
Expand Down Expand Up @@ -54,7 +54,7 @@ You can run upstream's benchmarks with:
```console
$ git clone https://github.com/ulfjack/ryu c-ryu
$ cd c-ryu
$ bazel run -c opt //ryu/benchmark:ryu_benchmark --
$ bazel run -c opt //ryu/benchmark:ryu_benchmark
```

And the same benchmark against our implementation with:
Expand Down
7 changes: 4 additions & 3 deletions fuzz/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
target
corpus
artifacts
artifacts/
corpus/
coverage/
target/
3 changes: 3 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ arbitrary = { version = "1", features = ["derive"] }
libfuzzer-sys = "0.4"
ryu-js = { path = ".." }

[features]
small = ["ryu-js/small"]

[[bin]]
name = "fuzz_ryu_js"
path = "fuzz_targets/fuzz_ryu_js.rs"
Expand Down
10 changes: 9 additions & 1 deletion src/buffer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const BUFFER_SIZE: usize = MAX_BUFFER_SIZE;
/// let printed = buffer.format_finite(1.234);
/// assert_eq!(printed, "1.234");
/// ```
#[derive(Copy, Clone)]
#[derive(Copy)]
pub struct Buffer {
bytes: [MaybeUninit<u8>; BUFFER_SIZE],
}
Expand Down Expand Up @@ -119,6 +119,14 @@ impl Buffer {
}
}

impl Clone for Buffer {
#[inline]
#[allow(clippy::non_canonical_clone_impl)] // false positive https://github.com/rust-lang/rust-clippy/issues/11072
fn clone(&self) -> Self {
Buffer::new()
}
}

impl Default for Buffer {
#[inline]
#[cfg_attr(feature = "no-panic", no_panic)]
Expand Down
10 changes: 6 additions & 4 deletions src/d2s.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

use crate::common::*;
use crate::common::{log10_pow2, log10_pow5, pow5bits};
#[cfg(not(feature = "small"))]
pub use crate::d2s_full_table::*;
use crate::d2s_intrinsics::*;
pub use crate::d2s_full_table::{DOUBLE_POW5_INV_SPLIT, DOUBLE_POW5_SPLIT};
use crate::d2s_intrinsics::{
div10, div100, div5, mul_shift_all_64, multiple_of_power_of_2, multiple_of_power_of_5,
};
#[cfg(feature = "small")]
pub use crate::d2s_small_table::*;
pub use crate::d2s_small_table::{compute_inv_pow5, compute_pow5};
use core::mem::MaybeUninit;

pub const DOUBLE_MANTISSA_BITS: u32 = 52;
Expand Down
10 changes: 5 additions & 5 deletions src/d2s_intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ pub fn div100(x: u64) -> u64 {
}

#[cfg_attr(feature = "no-panic", inline)]
fn pow5_factor(mut value: u64) -> u32 {
pub(crate) fn pow5_factor(mut value: u64) -> u32 {
const M_INV_5: u64 = 14757395258967641293; // 5 * m_inv_5 = 1 (mod 2^64)
const N_DIV_5: u64 = 3689348814741910323; // #{ n | n = 0 (mod 2^64) } = 2^64 / 5
let mut count = 0u32;
loop {
debug_assert!(value != 0);
let q = div5(value);
let r = (value as u32).wrapping_sub(5u32.wrapping_mul(q as u32));
if r != 0 {
value = value.wrapping_mul(M_INV_5);
if value > N_DIV_5 {
break;
}
value = q;
count += 1;
}
count
Expand Down
2 changes: 1 addition & 1 deletion src/d2s_small_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

use crate::common::*;
use crate::common::pow5bits;

pub static DOUBLE_POW5_INV_SPLIT2: [(u64, u64); 15] = [
(1, 2305843009213693952),
Expand Down
6 changes: 4 additions & 2 deletions src/f2s.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

use crate::common::*;
use crate::f2s_intrinsics::*;
use crate::common::{log10_pow2, log10_pow5, pow5bits};
use crate::f2s_intrinsics::{
mul_pow5_div_pow2, mul_pow5_inv_div_pow2, multiple_of_power_of_2_32, multiple_of_power_of_5_32,
};

pub const FLOAT_MANTISSA_BITS: u32 = 23;
pub const FLOAT_EXPONENT_BITS: u32 = 8;
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
clippy::missing_panics_doc,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::needless_doctest_main,
clippy::similar_names,
clippy::too_many_lines,
clippy::unreadable_literal,
Expand Down
2 changes: 1 addition & 1 deletion src/pretty/exponent.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::digit_table::*;
use crate::digit_table::DIGIT_TABLE;
use core::ptr;

#[cfg_attr(feature = "no-panic", inline)]
Expand Down
2 changes: 1 addition & 1 deletion src/pretty/mantissa.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::digit_table::*;
use crate::digit_table::DIGIT_TABLE;
use core::ptr;

#[cfg_attr(feature = "no-panic", inline)]
Expand Down
10 changes: 6 additions & 4 deletions src/pretty/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
mod exponent;
mod mantissa;

use self::exponent::*;
use self::mantissa::*;
use self::exponent::{write_exponent2, write_exponent3};
use self::mantissa::{write_mantissa, write_mantissa_long};
use crate::common;
use crate::d2s::{self, *};
use crate::f2s::*;
use crate::d2s::{self, d2d, DOUBLE_EXPONENT_BITS, DOUBLE_MANTISSA_BITS};
use crate::f2s::{f2d, FLOAT_EXPONENT_BITS, FLOAT_MANTISSA_BITS};
use core::ptr;
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
Expand Down Expand Up @@ -54,6 +54,7 @@ pub use to_fixed::format64_to_fixed;
#[cfg_attr(feature = "no-panic", no_panic)]
pub unsafe fn format64(f: f64, result: *mut u8) -> usize {
debug_assert!(!result.is_null());

let bits = f.to_bits();
let sign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
let ieee_mantissa = bits & ((1u64 << DOUBLE_MANTISSA_BITS) - 1);
Expand Down Expand Up @@ -160,6 +161,7 @@ pub unsafe fn format64(f: f64, result: *mut u8) -> usize {
#[cfg_attr(feature = "no-panic", no_panic)]
pub unsafe fn format32(f: f32, result: *mut u8) -> usize {
debug_assert!(!result.is_null());

let bits = f.to_bits();
let sign = ((bits >> (FLOAT_MANTISSA_BITS + FLOAT_EXPONENT_BITS)) & 1) != 0;
let ieee_mantissa = bits & ((1u32 << FLOAT_MANTISSA_BITS) - 1);
Expand Down
4 changes: 2 additions & 2 deletions src/s2d.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::common::*;
use crate::common::{ceil_log2_pow5, log2_pow5};
use crate::d2s;
use crate::d2s_intrinsics::*;
use crate::d2s_intrinsics::{mul_shift_64, multiple_of_power_of_2, multiple_of_power_of_5};
use crate::parse::Error;
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
Expand Down
6 changes: 4 additions & 2 deletions src/s2f.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::common::*;
use crate::common::{ceil_log2_pow5, log2_pow5};
use crate::f2s;
use crate::f2s_intrinsics::*;
use crate::f2s_intrinsics::{
mul_pow5_div_pow2, mul_pow5_inv_div_pow2, multiple_of_power_of_2_32, multiple_of_power_of_5_32,
};
use crate::parse::Error;
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
Expand Down
2 changes: 1 addition & 1 deletion tests/common_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#[path = "../src/common.rs"]
mod common;

use common::*;
use common::{ceil_log2_pow5, decimal_length9, log10_pow2, log10_pow5};

#[test]
fn test_decimal_length9() {
Expand Down
72 changes: 72 additions & 0 deletions tests/d2s_intrinsics_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Translated from C to Rust. The original C code can be found at
// https://github.com/ulfjack/ryu and carries the following license:
//
// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
// (See accompanying file LICENSE-Apache or copy at
// http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE-Boost or copy at
// https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

#![allow(dead_code)]
#![allow(
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::unreadable_literal
)]

#[path = "../src/d2s_intrinsics.rs"]
mod d2s_intrinsics;

use d2s_intrinsics::pow5_factor;

#[test]
fn test_pow5_factor() {
assert_eq!(0, pow5_factor(1));
assert_eq!(0, pow5_factor(2));
assert_eq!(0, pow5_factor(3));
assert_eq!(0, pow5_factor(4));
assert_eq!(1, pow5_factor(5));
assert_eq!(0, pow5_factor(6));
assert_eq!(0, pow5_factor(7));
assert_eq!(0, pow5_factor(8));
assert_eq!(0, pow5_factor(9));
assert_eq!(1, pow5_factor(10));

assert_eq!(0, pow5_factor(12));
assert_eq!(0, pow5_factor(14));
assert_eq!(0, pow5_factor(16));
assert_eq!(0, pow5_factor(18));
assert_eq!(1, pow5_factor(20));

assert_eq!(2, pow5_factor(5 * 5));
assert_eq!(3, pow5_factor(5 * 5 * 5));
assert_eq!(4, pow5_factor(5 * 5 * 5 * 5));
assert_eq!(5, pow5_factor(5 * 5 * 5 * 5 * 5));
assert_eq!(6, pow5_factor(5 * 5 * 5 * 5 * 5 * 5));
assert_eq!(7, pow5_factor(5 * 5 * 5 * 5 * 5 * 5 * 5));
assert_eq!(8, pow5_factor(5 * 5 * 5 * 5 * 5 * 5 * 5 * 5));
assert_eq!(9, pow5_factor(5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5));
assert_eq!(10, pow5_factor(5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5));

assert_eq!(0, pow5_factor(42));
assert_eq!(1, pow5_factor(42 * 5));
assert_eq!(2, pow5_factor(42 * 5 * 5));
assert_eq!(3, pow5_factor(42 * 5 * 5 * 5));
assert_eq!(4, pow5_factor(42 * 5 * 5 * 5 * 5));
assert_eq!(5, pow5_factor(42 * 5 * 5 * 5 * 5 * 5));

assert_eq!(27, pow5_factor(7450580596923828125)); // 5^27, largest power of 5 < 2^64.
assert_eq!(1, pow5_factor(18446744073709551615)); // 2^64 - 1, largest multiple of 5 < 2^64.
assert_eq!(0, pow5_factor(18446744073709551614)); // 2^64 - 2, largest non-multiple of 5 < 2^64.
}
4 changes: 2 additions & 2 deletions tests/d2s_table_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ mod d2s_intrinsics;
#[path = "../src/d2s_small_table.rs"]
mod d2s_small_table;

use d2s_full_table::*;
use d2s_small_table::*;
use d2s_full_table::{DOUBLE_POW5_INV_SPLIT, DOUBLE_POW5_SPLIT};
use d2s_small_table::{compute_inv_pow5, compute_pow5};

#[test]
fn test_compute_pow5() {
Expand Down
12 changes: 12 additions & 0 deletions tests/d2s_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ fn test_non_finite() {
}
}

#[test]
fn test_basic() {
assert_eq!(pretty(0.0), "0");
assert_eq!(pretty(-0.0), "0");
assert_eq!(pretty(1.0), "1");
assert_eq!(pretty(-1.0), "-1");
assert_eq!(pretty(f64::NAN.copysign(1.0)), "NaN");
assert_eq!(pretty(f64::NAN.copysign(-1.0)), "NaN");
assert_eq!(pretty(f64::INFINITY), "Infinity");
assert_eq!(pretty(f64::NEG_INFINITY), "-Infinity");
}

#[test]
fn test_switch_to_subnormal() {
check!(2.2250738585072014e-308);
Expand Down
3 changes: 2 additions & 1 deletion tests/f2s_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ fn test_basic() {
assert_eq!(pretty(-0.0), "0");
assert_eq!(pretty(1.0), "1");
assert_eq!(pretty(-1.0), "-1");
assert_eq!(pretty(f32::NAN), "NaN");
assert_eq!(pretty(f32::NAN.copysign(1.0)), "NaN");
assert_eq!(pretty(f32::NAN.copysign(-1.0)), "NaN");
assert_eq!(pretty(f32::INFINITY), "Infinity");
assert_eq!(pretty(f32::NEG_INFINITY), "-Infinity");
}
Expand Down

0 comments on commit 3bd7789

Please sign in to comment.