aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-15 21:45:24 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-15 21:45:24 +0000
commit05da7a31d0bff142b4e3817d028287cf69c825cd (patch)
tree87a8aab98a66595cccf5a7c95c7db70e8d5d51a6
parentd6e2173bf8206b23c780225ba4c813dda4dea598 (diff)
parent17edc3d1294b4aec6e1ff6ca68512b560cfd9bc9 (diff)
downloadryu-05da7a31d0bff142b4e3817d028287cf69c825cd.tar.gz
Change-Id: Id5d7750bc5cfe3039b35480df556c22f267cf08a
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--.clippy.toml1
-rw-r--r--.github/workflows/ci.yml26
-rw-r--r--Android.bp82
-rw-r--r--Cargo.toml18
-rw-r--r--Cargo.toml.orig9
-rw-r--r--METADATA10
-rw-r--r--README.md26
-rw-r--r--TEST_MAPPING93
-rw-r--r--build.rs40
-rw-r--r--cargo2android.json3
-rw-r--r--src/buffer/mod.rs28
-rw-r--r--src/d2s.rs60
-rw-r--r--src/d2s_intrinsics.rs82
-rw-r--r--src/d2s_small_table.rs71
-rw-r--r--src/lib.rs40
-rw-r--r--src/pretty/exponent.rs6
-rw-r--r--src/pretty/mantissa.rs48
-rw-r--r--src/pretty/mod.rs6
-rw-r--r--src/s2d.rs5
-rw-r--r--src/s2f.rs26
-rw-r--r--tests/common_test.rs8
-rw-r--r--tests/d2s_table_test.rs9
-rw-r--r--tests/d2s_test.rs10
-rw-r--r--tests/f2s_test.rs8
-rw-r--r--tests/s2d_test.rs37
-rw-r--r--tests/s2f_test.rs33
27 files changed, 338 insertions, 454 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index af83192..5e45238 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,5 @@
{
"git": {
- "sha1": "fad77e77469c6e1ce51abc9d9d111668b3b65941"
- },
- "path_in_vcs": ""
-} \ No newline at end of file
+ "sha1": "9edbbd939fa80fb364d0a1ae65ff05efbc2ac894"
+ }
+}
diff --git a/.clippy.toml b/.clippy.toml
deleted file mode 100644
index 0a54853..0000000
--- a/.clippy.toml
+++ /dev/null
@@ -1 +0,0 @@
-msrv = "1.36.0"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 51809c3..ea91ef1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -19,16 +19,15 @@ jobs:
with:
toolchain: ${{matrix.rust}}
- run: cargo test
- - run: cargo test --features small
- run: cargo build --tests --features no-panic --release
if: matrix.rust == 'nightly'
msrv:
- name: Rust 1.36.0
+ name: Rust 1.31.0
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - uses: dtolnay/rust-toolchain@1.36.0
+ - uses: dtolnay/rust-toolchain@1.31.0
- run: cargo build
- run: cargo build --features small
@@ -40,24 +39,5 @@ jobs:
- uses: dtolnay/rust-toolchain@nightly
with:
components: miri
+ - run: cargo miri setup
- run: cargo miri test
- env:
- MIRIFLAGS: "-Zmiri-tag-raw-pointers"
-
- clippy:
- name: Clippy
- runs-on: ubuntu-latest
- if: github.event_name != 'pull_request'
- steps:
- - uses: actions/checkout@v2
- - uses: dtolnay/rust-toolchain@clippy
- - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic
-
- outdated:
- name: Outdated
- runs-on: ubuntu-latest
- if: github.event_name != 'pull_request'
- steps:
- - uses: actions/checkout@v2
- - uses: dtolnay/install@cargo-outdated
- - run: cargo outdated --exit-code 1
diff --git a/Android.bp b/Android.bp
index 851668c..d32ed19 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,88 +43,14 @@ rust_library {
name: "libryu",
host_supported: true,
crate_name: "ryu",
- cargo_env_compat: true,
- cargo_pkg_version: "1.0.9",
srcs: ["src/lib.rs"],
edition: "2018",
+ cfgs: [
+ "integer128",
+ "maybe_uninit",
+ ],
apex_available: [
"//apex_available:platform",
"com.android.virt",
],
}
-
-rust_defaults {
- name: "ryu_test_defaults",
- crate_name: "ryu",
- cargo_env_compat: true,
- cargo_pkg_version: "1.0.9",
- test_suites: ["general-tests"],
- auto_gen_config: true,
- edition: "2018",
- rustlibs: [
- "libnum_cpus",
- "librand",
- "librand_xorshift",
- "libryu",
- ],
-}
-
-rust_test {
- name: "ryu_test_tests_common_test",
- defaults: ["ryu_test_defaults"],
- host_supported: true,
- srcs: ["tests/common_test.rs"],
- test_options: {
- unit_test: true,
- },
-}
-
-rust_test {
- name: "ryu_test_tests_d2s_table_test",
- defaults: ["ryu_test_defaults"],
- host_supported: true,
- srcs: ["tests/d2s_table_test.rs"],
- test_options: {
- unit_test: true,
- },
-}
-
-rust_test {
- name: "ryu_test_tests_d2s_test",
- defaults: ["ryu_test_defaults"],
- host_supported: true,
- srcs: ["tests/d2s_test.rs"],
- test_options: {
- unit_test: true,
- },
-}
-
-rust_test {
- name: "ryu_test_tests_f2s_test",
- defaults: ["ryu_test_defaults"],
- host_supported: true,
- srcs: ["tests/f2s_test.rs"],
- test_options: {
- unit_test: true,
- },
-}
-
-rust_test {
- name: "ryu_test_tests_s2d_test",
- defaults: ["ryu_test_defaults"],
- host_supported: true,
- srcs: ["tests/s2d_test.rs"],
- test_options: {
- unit_test: true,
- },
-}
-
-rust_test {
- name: "ryu_test_tests_s2f_test",
- defaults: ["ryu_test_defaults"],
- host_supported: true,
- srcs: ["tests/s2f_test.rs"],
- test_options: {
- unit_test: true,
- },
-}
diff --git a/Cargo.toml b/Cargo.toml
index 5bb4325..3da4fcd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,23 +3,21 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
+# to registry (e.g., crates.io) dependencies
#
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
[package]
edition = "2018"
-rust-version = "1.36"
name = "ryu"
-version = "1.0.9"
+version = "1.0.5"
authors = ["David Tolnay <dtolnay@gmail.com>"]
-exclude = ["performance.png", "chart/**"]
description = "Fast floating point to string conversion"
documentation = "https://docs.rs/ryu"
readme = "README.md"
-categories = ["value-formatting"]
license = "Apache-2.0 OR BSL-1.0"
repository = "https://github.com/dtolnay/ryu"
[package.metadata.docs.rs]
@@ -31,10 +29,10 @@ optional = true
version = "1.8"
[dev-dependencies.rand]
-version = "0.8"
+version = "0.7"
[dev-dependencies.rand_xorshift]
-version = "0.3"
+version = "0.2"
[features]
small = []
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index af29dff..ad0ba2c 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,16 +1,13 @@
[package]
name = "ryu"
-version = "1.0.9" # don't forget to update html_root_url
+version = "1.0.5" # don't forget to update html_root_url
authors = ["David Tolnay <dtolnay@gmail.com>"]
license = "Apache-2.0 OR BSL-1.0"
description = "Fast floating point to string conversion"
repository = "https://github.com/dtolnay/ryu"
documentation = "https://docs.rs/ryu"
-categories = ["value-formatting"]
readme = "README.md"
-exclude = ["performance.png", "chart/**"]
edition = "2018"
-rust-version = "1.36"
[features]
# Use smaller lookup tables. Instead of storing every required power of
@@ -24,8 +21,8 @@ no-panic = { version = "0.1", optional = true }
[dev-dependencies]
num_cpus = "1.8"
-rand = "0.8"
-rand_xorshift = "0.3"
+rand = "0.7"
+rand_xorshift = "0.2"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
diff --git a/METADATA b/METADATA
index 15dcbf0..2a0d2f8 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/ryu/ryu-1.0.9.crate"
+ value: "https://static.crates.io/crates/ryu/ryu-1.0.5.crate"
}
- version: "1.0.9"
+ version: "1.0.5"
license_type: NOTICE
last_upgrade_date {
- year: 2022
- month: 3
- day: 1
+ year: 2020
+ month: 8
+ day: 21
}
}
diff --git a/README.md b/README.md
index b4149b0..bf718ed 100644
--- a/README.md
+++ b/README.md
@@ -15,19 +15,17 @@ 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.36; it
+*Requirements: this crate supports any compiler version back to rustc 1.31; it
uses nothing from the Rust standard library so is usable from no_std crates.*
[paper]: https://dl.acm.org/citation.cfm?id=3192369
-[upstream]: https://github.com/ulfjack/ryu/tree/abf76d252bc97300354857e64e80d4a2bf664291
+[upstream]: https://github.com/ulfjack/ryu/tree/1c413e127f8d02afd12eb6259bc80163722f1385
```toml
[dependencies]
ryu = "1.0"
```
-<br>
-
## Example
```rust
@@ -38,18 +36,14 @@ fn main() {
}
```
-<br>
-
-## Performance (lower is better)
-
-![performance](https://raw.githubusercontent.com/dtolnay/ryu/master/performance.png)
+## Performance
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
```
And the same benchmark against our implementation with:
@@ -75,10 +69,20 @@ standard library which you can run with:
$ cargo bench
```
-The benchmark shows Ryū approximately 2-5x faster than the standard library
+The benchmark shows Ryū approximately 4-10x faster than the standard library
across a range of f32 and f64 inputs. Measurements are in nanoseconds per
iteration; smaller is better.
+| type=f32 | 0.0 | 0.1234 | 2.718281828459045 | f32::MAX |
+|:--------:|:----:|:------:|:-----------------:|:--------:|
+| RYU | 3ns | 28ns | 23ns | 22ns |
+| STD | 40ns | 106ns | 128ns | 110ns |
+
+| type=f64 | 0.0 | 0.1234 | 2.718281828459045 | f64::MAX |
+|:--------:|:----:|:------:|:-----------------:|:--------:|
+| RYU | 3ns | 50ns | 35ns | 32ns |
+| STD | 39ns | 105ns | 128ns | 202ns |
+
## Formatting
This library tends to produce more human-readable output than the standard
diff --git a/TEST_MAPPING b/TEST_MAPPING
deleted file mode 100644
index 701f911..0000000
--- a/TEST_MAPPING
+++ /dev/null
@@ -1,93 +0,0 @@
-// Generated by update_crate_tests.py for tests that depend on this crate.
-{
- "imports": [
- {
- "path": "external/rust/crates/base64"
- },
- {
- "path": "external/rust/crates/bitflags"
- },
- {
- "path": "external/rust/crates/either"
- },
- {
- "path": "external/rust/crates/rand_chacha"
- },
- {
- "path": "external/rust/crates/tinytemplate"
- },
- {
- "path": "external/rust/crates/tinyvec"
- },
- {
- "path": "external/rust/crates/unicode-xid"
- },
- {
- "path": "external/rust/crates/url"
- }
- ],
- "presubmit": [
- {
- "name": "ZipFuseTest"
- },
- {
- "name": "authfs_device_test_src_lib"
- },
- {
- "name": "microdroid_manager_test"
- },
- {
- "name": "ryu_test_tests_common_test"
- },
- {
- "name": "ryu_test_tests_d2s_table_test"
- },
- {
- "name": "ryu_test_tests_d2s_test"
- },
- {
- "name": "ryu_test_tests_f2s_test"
- },
- {
- "name": "ryu_test_tests_s2d_test"
- },
- {
- "name": "ryu_test_tests_s2f_test"
- },
- {
- "name": "virtualizationservice_device_test"
- }
- ],
- "presubmit-rust": [
- {
- "name": "ZipFuseTest"
- },
- {
- "name": "authfs_device_test_src_lib"
- },
- {
- "name": "microdroid_manager_test"
- },
- {
- "name": "ryu_test_tests_common_test"
- },
- {
- "name": "ryu_test_tests_d2s_table_test"
- },
- {
- "name": "ryu_test_tests_d2s_test"
- },
- {
- "name": "ryu_test_tests_f2s_test"
- },
- {
- "name": "ryu_test_tests_s2d_test"
- },
- {
- "name": "ryu_test_tests_s2f_test"
- },
- {
- "name": "virtualizationservice_device_test"
- }
- ]
-}
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..f48477a
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,40 @@
+use std::env;
+use std::process::Command;
+use std::str::{self, FromStr};
+
+// The rustc-cfg strings below are *not* public API. Please let us know by
+// opening a GitHub issue if your build environment requires some way to enable
+// these cfgs other than by executing our build script.
+fn main() {
+ let minor = match rustc_minor_version() {
+ Some(minor) => minor,
+ None => return,
+ };
+
+ let target = env::var("TARGET").unwrap();
+ let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
+
+ // 128-bit integers disabled on Emscripten targets as Emscripten doesn't
+ // currently support integers larger than 64 bits.
+ if !emscripten {
+ println!("cargo:rustc-cfg=integer128");
+ }
+
+ // MaybeUninit<T> stabilized in Rust 1.36:
+ // https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html
+ if minor >= 36 {
+ println!("cargo:rustc-cfg=maybe_uninit");
+ }
+}
+
+fn rustc_minor_version() -> Option<u32> {
+ let rustc = env::var_os("RUSTC")?;
+ let output = Command::new(rustc).arg("--version").output().ok()?;
+ let version = str::from_utf8(&output.stdout).ok()?;
+ let mut pieces = version.split('.');
+ if pieces.next() != Some("rustc 1") {
+ return None;
+ }
+ let next = pieces.next()?;
+ u32::from_str(next).ok()
+}
diff --git a/cargo2android.json b/cargo2android.json
index ac56e26..42b7833 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -5,6 +5,5 @@
],
"dependencies": true,
"device": true,
- "run": true,
- "tests": true
+ "run": true
} \ No newline at end of file
diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs
index 2ccd9b0..df21fe0 100644
--- a/src/buffer/mod.rs
+++ b/src/buffer/mod.rs
@@ -1,12 +1,13 @@
use crate::raw;
+#[cfg(maybe_uninit)]
use core::mem::MaybeUninit;
-use core::{slice, str};
+use core::{mem, slice, str};
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
-const NAN: &str = "NaN";
-const INFINITY: &str = "inf";
-const NEG_INFINITY: &str = "-inf";
+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.
///
@@ -18,7 +19,10 @@ const NEG_INFINITY: &str = "-inf";
/// assert_eq!(printed, "1.234");
/// ```
pub struct Buffer {
+ #[cfg(maybe_uninit)]
bytes: [MaybeUninit<u8>; 24],
+ #[cfg(not(maybe_uninit))]
+ bytes: [u8; 24],
}
impl Buffer {
@@ -27,8 +31,14 @@ impl Buffer {
#[inline]
#[cfg_attr(feature = "no-panic", no_panic)]
pub fn new() -> Self {
+ // assume_init is safe here, since this is an array of MaybeUninit, which does not need
+ // to be initialized.
+ #[cfg(maybe_uninit)]
let bytes = [MaybeUninit::<u8>::uninit(); 24];
- Buffer { bytes }
+ #[cfg(not(maybe_uninit))]
+ let bytes = unsafe { mem::uninitialized() };
+
+ Buffer { bytes: bytes }
}
/// Print a floating point number into this buffer and return a reference to
@@ -115,7 +125,7 @@ impl Sealed for f32 {
#[inline]
fn is_nonfinite(self) -> bool {
const EXP_MASK: u32 = 0x7f800000;
- let bits = self.to_bits();
+ let bits = unsafe { mem::transmute::<f32, u32>(self) };
bits & EXP_MASK == EXP_MASK
}
@@ -124,7 +134,7 @@ impl Sealed for f32 {
fn format_nonfinite(self) -> &'static str {
const MANTISSA_MASK: u32 = 0x007fffff;
const SIGN_MASK: u32 = 0x80000000;
- let bits = self.to_bits();
+ let bits = unsafe { mem::transmute::<f32, u32>(self) };
if bits & MANTISSA_MASK != 0 {
NAN
} else if bits & SIGN_MASK != 0 {
@@ -144,7 +154,7 @@ impl Sealed for f64 {
#[inline]
fn is_nonfinite(self) -> bool {
const EXP_MASK: u64 = 0x7ff0000000000000;
- let bits = self.to_bits();
+ let bits = unsafe { mem::transmute::<f64, u64>(self) };
bits & EXP_MASK == EXP_MASK
}
@@ -153,7 +163,7 @@ impl Sealed for f64 {
fn format_nonfinite(self) -> &'static str {
const MANTISSA_MASK: u64 = 0x000fffffffffffff;
const SIGN_MASK: u64 = 0x8000000000000000;
- let bits = self.to_bits();
+ let bits = unsafe { mem::transmute::<f64, u64>(self) };
if bits & MANTISSA_MASK != 0 {
NAN
} else if bits & SIGN_MASK != 0 {
diff --git a/src/d2s.rs b/src/d2s.rs
index 392577a..862fd5f 100644
--- a/src/d2s.rs
+++ b/src/d2s.rs
@@ -24,6 +24,9 @@ pub use crate::d2s_full_table::*;
use crate::d2s_intrinsics::*;
#[cfg(feature = "small")]
pub use crate::d2s_small_table::*;
+#[cfg(not(maybe_uninit))]
+use core::mem;
+#[cfg(maybe_uninit)]
use core::mem::MaybeUninit;
pub const DOUBLE_MANTISSA_BITS: u32 = 52;
@@ -114,7 +117,14 @@ pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
let mut vr: u64;
let mut vp: u64;
let mut vm: u64;
+ #[cfg(not(maybe_uninit))]
+ {
+ vp = unsafe { mem::uninitialized() };
+ vm = unsafe { mem::uninitialized() };
+ }
+ #[cfg(maybe_uninit)]
let mut vp_uninit: MaybeUninit<u64> = MaybeUninit::uninit();
+ #[cfg(maybe_uninit)]
let mut vm_uninit: MaybeUninit<u64> = MaybeUninit::uninit();
let e10: i32;
let mut vm_is_trailing_zeros = false;
@@ -137,13 +147,30 @@ pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
DOUBLE_POW5_INV_SPLIT.get_unchecked(q as usize)
},
i as u32,
- vp_uninit.as_mut_ptr(),
- vm_uninit.as_mut_ptr(),
+ #[cfg(maybe_uninit)]
+ {
+ vp_uninit.as_mut_ptr()
+ },
+ #[cfg(not(maybe_uninit))]
+ {
+ &mut vp
+ },
+ #[cfg(maybe_uninit)]
+ {
+ vm_uninit.as_mut_ptr()
+ },
+ #[cfg(not(maybe_uninit))]
+ {
+ &mut vm
+ },
mm_shift,
)
};
- vp = unsafe { vp_uninit.assume_init() };
- vm = unsafe { vm_uninit.assume_init() };
+ #[cfg(maybe_uninit)]
+ {
+ vp = unsafe { vp_uninit.assume_init() };
+ vm = unsafe { vm_uninit.assume_init() };
+ }
if q <= 21 {
// This should use q <= 22, but I think 21 is also safe. Smaller values
// may still be safe, but it's more difficult to reason about them.
@@ -179,13 +206,30 @@ pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
DOUBLE_POW5_SPLIT.get_unchecked(i as usize)
},
j as u32,
- vp_uninit.as_mut_ptr(),
- vm_uninit.as_mut_ptr(),
+ #[cfg(maybe_uninit)]
+ {
+ vp_uninit.as_mut_ptr()
+ },
+ #[cfg(not(maybe_uninit))]
+ {
+ &mut vp
+ },
+ #[cfg(maybe_uninit)]
+ {
+ vm_uninit.as_mut_ptr()
+ },
+ #[cfg(not(maybe_uninit))]
+ {
+ &mut vm
+ },
mm_shift,
)
};
- vp = unsafe { vp_uninit.assume_init() };
- vm = unsafe { vm_uninit.assume_init() };
+ #[cfg(maybe_uninit)]
+ {
+ vp = unsafe { vp_uninit.assume_init() };
+ vm = unsafe { vm_uninit.assume_init() };
+ }
if q <= 1 {
// {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits.
// mv = 4 * m2, so it always has at least two trailing 0 bits.
diff --git a/src/d2s_intrinsics.rs b/src/d2s_intrinsics.rs
index f244a4d..918ccab 100644
--- a/src/d2s_intrinsics.rs
+++ b/src/d2s_intrinsics.rs
@@ -20,6 +20,46 @@
use core::ptr;
+// Returns (lo, hi).
+#[cfg(not(integer128))]
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn umul128(a: u64, b: u64) -> (u64, u64) {
+ let a_lo = a as u32;
+ let a_hi = (a >> 32) as u32;
+ let b_lo = b as u32;
+ let b_hi = (b >> 32) as u32;
+
+ let b00 = a_lo as u64 * b_lo as u64;
+ let b01 = a_lo as u64 * b_hi as u64;
+ let b10 = a_hi as u64 * b_lo as u64;
+ let b11 = a_hi as u64 * b_hi as u64;
+
+ let b00_lo = b00 as u32;
+ let b00_hi = (b00 >> 32) as u32;
+
+ let mid1 = b10 + b00_hi as u64;
+ let mid1_lo = mid1 as u32;
+ let mid1_hi = (mid1 >> 32) as u32;
+
+ let mid2 = b01 + mid1_lo as u64;
+ let mid2_lo = mid2 as u32;
+ let mid2_hi = (mid2 >> 32) as u32;
+
+ let p_hi = b11 + mid1_hi as u64 + mid2_hi as u64;
+ let p_lo = ((mid2_lo as u64) << 32) | b00_lo as u64;
+
+ (p_lo, p_hi)
+}
+
+#[cfg(not(integer128))]
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn shiftright128(lo: u64, hi: u64, dist: u32) -> u64 {
+ // We don't need to handle the case dist >= 64 here (see above).
+ debug_assert!(dist > 0);
+ debug_assert!(dist < 64);
+ (hi << (64 - dist)) | (lo >> dist)
+}
+
#[cfg_attr(feature = "no-panic", inline)]
pub fn div5(x: u64) -> u64 {
x / 5
@@ -67,6 +107,7 @@ pub fn multiple_of_power_of_2(value: u64, p: u32) -> bool {
(value & ((1u64 << p) - 1)) == 0
}
+#[cfg(integer128)]
#[cfg_attr(feature = "no-panic", inline)]
pub fn mul_shift_64(m: u64, mul: &(u64, u64), j: u32) -> u64 {
let b0 = m as u128 * mul.0 as u128;
@@ -74,6 +115,7 @@ pub fn mul_shift_64(m: u64, mul: &(u64, u64), j: u32) -> u64 {
(((b0 >> 64) + b2) >> (j - 64)) as u64
}
+#[cfg(integer128)]
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn mul_shift_all_64(
m: u64,
@@ -87,3 +129,43 @@ pub unsafe fn mul_shift_all_64(
ptr::write(vm, mul_shift_64(4 * m - 1 - mm_shift as u64, mul, j));
mul_shift_64(4 * m, mul, j)
}
+
+#[cfg(not(integer128))]
+#[cfg_attr(feature = "no-panic", inline)]
+pub unsafe fn mul_shift_all_64(
+ mut m: u64,
+ mul: &(u64, u64),
+ j: u32,
+ vp: *mut u64,
+ vm: *mut u64,
+ mm_shift: u32,
+) -> u64 {
+ m <<= 1;
+ // m is maximum 55 bits
+ let (lo, tmp) = umul128(m, mul.0);
+ let (mut mid, mut hi) = umul128(m, mul.1);
+ mid = mid.wrapping_add(tmp);
+ hi = hi.wrapping_add((mid < tmp) as u64); // overflow into hi
+
+ let lo2 = lo.wrapping_add(mul.0);
+ let mid2 = mid.wrapping_add(mul.1).wrapping_add((lo2 < lo) as u64);
+ let hi2 = hi.wrapping_add((mid2 < mid) as u64);
+ ptr::write(vp, shiftright128(mid2, hi2, j - 64 - 1));
+
+ if mm_shift == 1 {
+ let lo3 = lo.wrapping_sub(mul.0);
+ let mid3 = mid.wrapping_sub(mul.1).wrapping_sub((lo3 > lo) as u64);
+ let hi3 = hi.wrapping_sub((mid3 > mid) as u64);
+ ptr::write(vm, shiftright128(mid3, hi3, j - 64 - 1));
+ } else {
+ let lo3 = lo + lo;
+ let mid3 = mid.wrapping_add(mid).wrapping_add((lo3 < lo) as u64);
+ let hi3 = hi.wrapping_add(hi).wrapping_add((mid3 < mid) as u64);
+ let lo4 = lo3.wrapping_sub(mul.0);
+ let mid4 = mid3.wrapping_sub(mul.1).wrapping_sub((lo4 > lo3) as u64);
+ let hi4 = hi3.wrapping_sub((mid4 > mid3) as u64);
+ ptr::write(vm, shiftright128(mid4, hi4, j - 64));
+ }
+
+ shiftright128(mid, hi, j - 64 - 1)
+}
diff --git a/src/d2s_small_table.rs b/src/d2s_small_table.rs
index 262fc04..08519a2 100644
--- a/src/d2s_small_table.rs
+++ b/src/d2s_small_table.rs
@@ -19,8 +19,10 @@
// KIND, either express or implied.
use crate::common::*;
+#[cfg(not(integer128))]
+use crate::d2s_intrinsics::*;
-pub static DOUBLE_POW5_INV_SPLIT2: [(u64, u64); 15] = [
+pub static DOUBLE_POW5_INV_SPLIT2: [(u64, u64); 13] = [
(1, 2305843009213693952),
(5955668970331000884, 1784059615882449851),
(8982663654677661702, 1380349269358112757),
@@ -34,8 +36,6 @@ pub static DOUBLE_POW5_INV_SPLIT2: [(u64, u64); 15] = [
(12533209867169019542, 1418129833677084982),
(5577825024675947042, 2194449627517475473),
(11006974540203867551, 1697873161311732311),
- (10313493231639821582, 1313665730009899186),
- (12701016819766672773, 2032799256770390445),
];
pub static POW5_INV_OFFSETS: [u32; 19] = [
@@ -96,6 +96,7 @@ pub static DOUBLE_POW5_TABLE: [u64; 26] = [
];
// Computes 5^i in the form required by Ryū.
+#[cfg(integer128)]
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
let base = i / DOUBLE_POW5_TABLE.len() as u32;
@@ -111,7 +112,7 @@ pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
let b0 = m as u128 * mul.0 as u128;
let b2 = m as u128 * mul.1 as u128;
let delta = pow5bits(i as i32) - pow5bits(base2 as i32);
- debug_assert!(i / 16 < POW5_OFFSETS.len() as u32);
+ debug_assert!(base < POW5_OFFSETS.len() as u32);
let shifted_sum = (b0 >> delta)
+ (b2 << (64 - delta))
+ ((*POW5_OFFSETS.get_unchecked((i / 16) as usize) >> ((i % 16) << 1)) & 3) as u128;
@@ -119,6 +120,7 @@ pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
}
// Computes 5^-i in the form required by Ryū.
+#[cfg(integer128)]
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn compute_inv_pow5(i: u32) -> (u64, u64) {
let base = (i + DOUBLE_POW5_TABLE.len() as u32 - 1) / DOUBLE_POW5_TABLE.len() as u32;
@@ -140,3 +142,64 @@ pub unsafe fn compute_inv_pow5(i: u32) -> (u64, u64) {
+ ((*POW5_INV_OFFSETS.get_unchecked((i / 16) as usize) >> ((i % 16) << 1)) & 3) as u128;
(shifted_sum as u64, (shifted_sum >> 64) as u64)
}
+
+// Computes 5^i in the form required by Ryū, and stores it in the given pointer.
+#[cfg(not(integer128))]
+#[cfg_attr(feature = "no-panic", inline)]
+pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
+ let base = i / DOUBLE_POW5_TABLE.len() as u32;
+ let base2 = base * DOUBLE_POW5_TABLE.len() as u32;
+ let offset = i - base2;
+ debug_assert!(base < DOUBLE_POW5_SPLIT2.len() as u32);
+ let mul = *DOUBLE_POW5_SPLIT2.get_unchecked(base as usize);
+ if offset == 0 {
+ return mul;
+ }
+ debug_assert!(offset < DOUBLE_POW5_TABLE.len() as u32);
+ let m = *DOUBLE_POW5_TABLE.get_unchecked(offset as usize);
+ let (low1, mut high1) = umul128(m, mul.1);
+ let (low0, high0) = umul128(m, mul.0);
+ let sum = high0 + low1;
+ if sum < high0 {
+ high1 += 1; // overflow into high1
+ }
+ // high1 | sum | low0
+ let delta = pow5bits(i as i32) - pow5bits(base2 as i32);
+ debug_assert!(base < POW5_OFFSETS.len() as u32);
+ (
+ shiftright128(low0, sum, delta as u32)
+ + ((*POW5_OFFSETS.get_unchecked((i / 16) as usize) >> ((i % 16) << 1)) & 3) as u64,
+ shiftright128(sum, high1, delta as u32),
+ )
+}
+
+// Computes 5^-i in the form required by Ryū, and stores it in the given pointer.
+#[cfg(not(integer128))]
+#[cfg_attr(feature = "no-panic", inline)]
+pub unsafe fn compute_inv_pow5(i: u32) -> (u64, u64) {
+ let base = (i + DOUBLE_POW5_TABLE.len() as u32 - 1) / DOUBLE_POW5_TABLE.len() as u32;
+ let base2 = base * DOUBLE_POW5_TABLE.len() as u32;
+ let offset = base2 - i;
+ debug_assert!(base < DOUBLE_POW5_INV_SPLIT2.len() as u32);
+ let mul = *DOUBLE_POW5_INV_SPLIT2.get_unchecked(base as usize); // 1/5^base2
+ if offset == 0 {
+ return mul;
+ }
+ debug_assert!(offset < DOUBLE_POW5_TABLE.len() as u32);
+ let m = *DOUBLE_POW5_TABLE.get_unchecked(offset as usize);
+ let (low1, mut high1) = umul128(m, mul.1);
+ let (low0, high0) = umul128(m, mul.0 - 1);
+ let sum = high0 + low1;
+ if sum < high0 {
+ high1 += 1; // overflow into high1
+ }
+ // high1 | sum | low0
+ let delta = pow5bits(base2 as i32) - pow5bits(i as i32);
+ debug_assert!(base < POW5_INV_OFFSETS.len() as u32);
+ (
+ shiftright128(low0, sum, delta as u32)
+ + 1
+ + ((*POW5_INV_OFFSETS.get_unchecked((i / 16) as usize) >> ((i % 16) << 1)) & 3) as u64,
+ shiftright128(sum, high1, delta as u32),
+ )
+}
diff --git a/src/lib.rs b/src/lib.rs
index 0177efa..db6ee16 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -29,9 +29,7 @@
//! }
//! ```
//!
-//! ## Performance (lower is better)
-//!
-//! ![performance](https://raw.githubusercontent.com/dtolnay/ryu/master/performance.png)
+//! ## Performance
//!
//! You can run upstream's benchmarks with:
//!
@@ -64,10 +62,20 @@
//! $ cargo bench
//! ```
//!
-//! The benchmark shows Ryū approximately 2-5x faster than the standard library
+//! The benchmark shows Ryū approximately 4-10x faster than the standard library
//! across a range of f32 and f64 inputs. Measurements are in nanoseconds per
//! iteration; smaller is better.
//!
+//! | type=f32 | 0.0 | 0.1234 | 2.718281828459045 | f32::MAX |
+//! |:--------:|:----:|:------:|:-----------------:|:--------:|
+//! | RYU | 3ns | 28ns | 23ns | 22ns |
+//! | STD | 40ns | 106ns | 128ns | 110ns |
+//!
+//! | type=f64 | 0.0 | 0.1234 | 2.718281828459045 | f64::MAX |
+//! |:--------:|:----:|:------:|:-----------------:|:--------:|
+//! | RYU | 3ns | 50ns | 35ns | 32ns |
+//! | STD | 39ns | 105ns | 128ns | 202ns |
+//!
//! ## Formatting
//!
//! This library tends to produce more human-readable output than the standard
@@ -81,25 +89,11 @@
//! notation.
#![no_std]
-#![doc(html_root_url = "https://docs.rs/ryu/1.0.9")]
-#![allow(
- clippy::cast_lossless,
- clippy::cast_possible_truncation,
- clippy::cast_possible_wrap,
- clippy::cast_sign_loss,
- clippy::checked_conversions,
- clippy::doc_markdown,
- clippy::expl_impl_clone_on_copy,
- clippy::if_not_else,
- clippy::many_single_char_names,
- clippy::missing_panics_doc,
- clippy::module_name_repetitions,
- clippy::must_use_candidate,
- clippy::similar_names,
- clippy::too_many_lines,
- clippy::unreadable_literal,
- clippy::unseparated_literal_suffix,
- clippy::wildcard_imports
+#![doc(html_root_url = "https://docs.rs/ryu/1.0.5")]
+#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
+#![cfg_attr(
+ feature = "cargo-clippy",
+ allow(cast_lossless, many_single_char_names, unreadable_literal,)
)]
mod buffer;
diff --git a/src/pretty/exponent.rs b/src/pretty/exponent.rs
index b72add5..84053d5 100644
--- a/src/pretty/exponent.rs
+++ b/src/pretty/exponent.rs
@@ -14,11 +14,11 @@ pub unsafe fn write_exponent3(mut k: isize, mut result: *mut u8) -> usize {
if k >= 100 {
*result = b'0' + (k / 100) as u8;
k %= 100;
- let d = DIGIT_TABLE.as_ptr().offset(k * 2);
+ 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.as_ptr().offset(k * 2);
+ let d = DIGIT_TABLE.get_unchecked(k as usize * 2);
ptr::copy_nonoverlapping(d, result, 2);
sign as usize + 2
} else {
@@ -38,7 +38,7 @@ pub unsafe fn write_exponent2(mut k: isize, mut result: *mut u8) -> usize {
debug_assert!(k < 100);
if k >= 10 {
- let d = DIGIT_TABLE.as_ptr().offset(k * 2);
+ let d = DIGIT_TABLE.get_unchecked(k as usize * 2);
ptr::copy_nonoverlapping(d, result, 2);
sign as usize + 2
} else {
diff --git a/src/pretty/mantissa.rs b/src/pretty/mantissa.rs
index 150c79c..e5fc202 100644
--- a/src/pretty/mantissa.rs
+++ b/src/pretty/mantissa.rs
@@ -15,26 +15,10 @@ pub unsafe fn write_mantissa_long(mut output: u64, mut result: *mut u8) {
let c1 = (c / 100) << 1;
let d0 = (d % 100) << 1;
let d1 = (d / 100) << 1;
- ptr::copy_nonoverlapping(
- DIGIT_TABLE.as_ptr().offset(c0 as isize),
- result.offset(-2),
- 2,
- );
- ptr::copy_nonoverlapping(
- DIGIT_TABLE.as_ptr().offset(c1 as isize),
- result.offset(-4),
- 2,
- );
- ptr::copy_nonoverlapping(
- DIGIT_TABLE.as_ptr().offset(d0 as isize),
- result.offset(-6),
- 2,
- );
- ptr::copy_nonoverlapping(
- DIGIT_TABLE.as_ptr().offset(d1 as isize),
- result.offset(-8),
- 2,
- );
+ 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);
@@ -47,35 +31,19 @@ pub unsafe fn write_mantissa(mut output: u32, mut result: *mut u8) {
output /= 10_000;
let c0 = (c % 100) << 1;
let c1 = (c / 100) << 1;
- ptr::copy_nonoverlapping(
- DIGIT_TABLE.as_ptr().offset(c0 as isize),
- result.offset(-2),
- 2,
- );
- ptr::copy_nonoverlapping(
- DIGIT_TABLE.as_ptr().offset(c1 as isize),
- result.offset(-4),
- 2,
- );
+ 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.as_ptr().offset(c as isize),
- result.offset(-2),
- 2,
- );
+ 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.as_ptr().offset(c as isize),
- result.offset(-2),
- 2,
- );
+ 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/src/pretty/mod.rs b/src/pretty/mod.rs
index b196a11..a82692d 100644
--- a/src/pretty/mod.rs
+++ b/src/pretty/mod.rs
@@ -6,7 +6,7 @@ use self::mantissa::*;
use crate::common;
use crate::d2s::{self, *};
use crate::f2s::*;
-use core::ptr;
+use core::{mem, ptr};
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
@@ -50,7 +50,7 @@ use no_panic::no_panic;
#[must_use]
#[cfg_attr(feature = "no-panic", no_panic)]
pub unsafe fn format64(f: f64, result: *mut u8) -> usize {
- let bits = f.to_bits();
+ 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 =
@@ -157,7 +157,7 @@ pub unsafe fn format64(f: f64, result: *mut u8) -> usize {
#[must_use]
#[cfg_attr(feature = "no-panic", no_panic)]
pub unsafe fn format32(f: f32, result: *mut u8) -> usize {
- let bits = f.to_bits();
+ 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 =
diff --git a/src/s2d.rs b/src/s2d.rs
index 152ca97..3d3808d 100644
--- a/src/s2d.rs
+++ b/src/s2d.rs
@@ -203,13 +203,12 @@ pub fn s2d(buffer: &[u8]) -> Result<f64, Error> {
let round_up = last_removed_bit != 0 && (!trailing_zeros || ((m2 >> shift) & 1) != 0);
let mut ieee_m2 = (m2 >> shift).wrapping_add(round_up as u64);
- debug_assert!(ieee_m2 <= 1_u64 << (d2s::DOUBLE_MANTISSA_BITS + 1));
- ieee_m2 &= (1_u64 << d2s::DOUBLE_MANTISSA_BITS) - 1;
- if ieee_m2 == 0 && round_up {
+ if ieee_m2 == (1_u64 << (d2s::DOUBLE_MANTISSA_BITS + 1)) {
// Due to how the IEEE represents +/-Infinity, we don't need to check
// for overflow here.
ieee_e2 += 1;
}
+ ieee_m2 &= (1_u64 << d2s::DOUBLE_MANTISSA_BITS) - 1;
let ieee = ((((signed_m as u64) << d2s::DOUBLE_EXPONENT_BITS) | ieee_e2 as u64)
<< d2s::DOUBLE_MANTISSA_BITS)
| ieee_m2;
diff --git a/src/s2f.rs b/src/s2f.rs
index 37c5417..d9e0744 100644
--- a/src/s2f.rs
+++ b/src/s2f.rs
@@ -153,29 +153,13 @@ pub fn s2f(buffer: &[u8]) -> Result<f32, Error> {
.wrapping_add(e10 as u32)
.wrapping_sub(ceil_log2_pow5(-e10) as u32)
.wrapping_sub(f2s::FLOAT_MANTISSA_BITS + 1) as i32;
-
- // We now compute [m10 * 10^e10 / 2^e2] = [m10 / (5^(-e10) 2^(e2-e10))].
let j = e2
.wrapping_sub(e10)
.wrapping_add(ceil_log2_pow5(-e10))
.wrapping_sub(1)
.wrapping_add(f2s::FLOAT_POW5_INV_BITCOUNT);
m2 = mul_pow5_inv_div_pow2(m10, -e10 as u32, j);
-
- // We also compute if the result is exact, i.e.,
- // [m10 / (5^(-e10) 2^(e2-e10))] == m10 / (5^(-e10) 2^(e2-e10))
- //
- // If e2-e10 >= 0, we need to check whether (5^(-e10) 2^(e2-e10))
- // divides m10, which is the case iff pow5(m10) >= -e10 AND pow2(m10) >=
- // e2-e10.
- //
- // If e2-e10 < 0, we have actually computed [m10 * 2^(e10 e2) /
- // 5^(-e10)] above, and we need to check whether 5^(-e10) divides (m10 *
- // 2^(e10-e2)), which is the case iff pow5(m10 * 2^(e10-e2)) = pow5(m10)
- // >= -e10.
- trailing_zeros = (e2 < e10
- || (e2 - e10 < 32 && multiple_of_power_of_2_32(m10, (e2 - e10) as u32)))
- && multiple_of_power_of_5_32(m10, -e10 as u32);
+ trailing_zeros = multiple_of_power_of_5_32(m10, -e10 as u32);
}
// Compute the final IEEE exponent.
@@ -210,16 +194,12 @@ pub fn s2f(buffer: &[u8]) -> Result<f32, Error> {
let round_up = last_removed_bit != 0 && (!trailing_zeros || ((m2 >> shift) & 1) != 0);
let mut ieee_m2 = (m2 >> shift).wrapping_add(round_up as u32);
- debug_assert!(ieee_m2 <= 1_u32 << (f2s::FLOAT_MANTISSA_BITS + 1));
- ieee_m2 &= (1_u32 << f2s::FLOAT_MANTISSA_BITS) - 1;
- if ieee_m2 == 0 && round_up {
- // Rounding up may overflow the mantissa.
- // In this case we move a trailing zero of the mantissa into the
- // exponent.
+ if ieee_m2 == (1_u32 << (f2s::FLOAT_MANTISSA_BITS + 1)) {
// Due to how the IEEE represents +/-Infinity, we don't need to check
// for overflow here.
ieee_e2 += 1;
}
+ ieee_m2 &= (1_u32 << f2s::FLOAT_MANTISSA_BITS) - 1;
let ieee = ((((signed_m as u32) << f2s::FLOAT_EXPONENT_BITS) | ieee_e2 as u32)
<< f2s::FLOAT_MANTISSA_BITS)
| ieee_m2;
diff --git a/tests/common_test.rs b/tests/common_test.rs
index 2f05b33..a6010e9 100644
--- a/tests/common_test.rs
+++ b/tests/common_test.rs
@@ -19,14 +19,6 @@
// KIND, either express or implied.
#![allow(dead_code)]
-#![allow(
- clippy::approx_constant,
- clippy::cast_possible_wrap,
- clippy::cast_sign_loss,
- clippy::excessive_precision,
- clippy::unreadable_literal,
- clippy::wildcard_imports
-)]
#[path = "../src/common.rs"]
mod common;
diff --git a/tests/d2s_table_test.rs b/tests/d2s_table_test.rs
index dce1be3..aa45c55 100644
--- a/tests/d2s_table_test.rs
+++ b/tests/d2s_table_test.rs
@@ -19,15 +19,6 @@
// KIND, either express or implied.
#![allow(dead_code)]
-#![allow(
- clippy::cast_lossless,
- clippy::cast_possible_truncation,
- clippy::cast_possible_wrap,
- clippy::cast_sign_loss,
- clippy::unreadable_literal,
- clippy::unseparated_literal_suffix,
- clippy::wildcard_imports
-)]
#[path = "../src/common.rs"]
mod common;
diff --git a/tests/d2s_test.rs b/tests/d2s_test.rs
index 368cab6..604ab69 100644
--- a/tests/d2s_test.rs
+++ b/tests/d2s_test.rs
@@ -18,16 +18,6 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
-#![allow(
- clippy::approx_constant,
- clippy::cast_lossless,
- clippy::float_cmp,
- clippy::int_plus_one,
- clippy::non_ascii_literal,
- clippy::unreadable_literal,
- clippy::unseparated_literal_suffix
-)]
-
#[macro_use]
mod macros;
diff --git a/tests/f2s_test.rs b/tests/f2s_test.rs
index 927fa7e..916250e 100644
--- a/tests/f2s_test.rs
+++ b/tests/f2s_test.rs
@@ -18,14 +18,6 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
-#![allow(
- clippy::approx_constant,
- clippy::float_cmp,
- clippy::non_ascii_literal,
- clippy::unreadable_literal,
- clippy::unseparated_literal_suffix
-)]
-
#[macro_use]
mod macros;
diff --git a/tests/s2d_test.rs b/tests/s2d_test.rs
index 7b42164..f51c1ed 100644
--- a/tests/s2d_test.rs
+++ b/tests/s2d_test.rs
@@ -20,35 +20,16 @@
#![cfg(not(feature = "small"))]
#![allow(dead_code)]
-#![allow(
- clippy::cast_lossless,
- clippy::cast_possible_truncation,
- clippy::cast_possible_wrap,
- clippy::cast_sign_loss,
- clippy::excessive_precision,
- clippy::float_cmp,
- clippy::manual_range_contains,
- clippy::similar_names,
- clippy::too_many_lines,
- clippy::unreadable_literal,
- clippy::unseparated_literal_suffix,
- clippy::wildcard_imports
-)]
#[path = "../src/common.rs"]
mod common;
-#[cfg(not(feature = "small"))]
#[path = "../src/d2s_full_table.rs"]
mod d2s_full_table;
#[path = "../src/d2s_intrinsics.rs"]
mod d2s_intrinsics;
-#[cfg(feature = "small")]
-#[path = "../src/d2s_small_table.rs"]
-mod d2s_small_table;
-
#[path = "../src/d2s.rs"]
mod d2s;
@@ -96,7 +77,6 @@ fn test_basic() {
assert_eq!(1.0, s2d(b"1e0").unwrap());
assert_eq!(1.0, s2d(b"1E0").unwrap());
assert_eq!(1.0, s2d(b"000001.000000").unwrap());
- assert_eq!(0.2316419, s2d(b"0.2316419").unwrap());
}
#[test]
@@ -148,20 +128,3 @@ fn test_issue157() {
s2d(b"1.2999999999999999E+154").unwrap(),
);
}
-
-#[test]
-fn test_issue173() {
- // Denormal boundary
- assert_eq!(
- 2.2250738585072012e-308,
- s2d(b"2.2250738585072012e-308").unwrap(),
- );
- assert_eq!(
- 2.2250738585072013e-308,
- s2d(b"2.2250738585072013e-308").unwrap(),
- );
- assert_eq!(
- 2.2250738585072014e-308,
- s2d(b"2.2250738585072014e-308").unwrap(),
- );
-}
diff --git a/tests/s2f_test.rs b/tests/s2f_test.rs
index 5bae935..f49824a 100644
--- a/tests/s2f_test.rs
+++ b/tests/s2f_test.rs
@@ -19,36 +19,16 @@
// KIND, either express or implied.
#![allow(dead_code)]
-#![allow(
- clippy::cast_lossless,
- clippy::cast_possible_truncation,
- clippy::cast_possible_wrap,
- clippy::cast_possible_wrap,
- clippy::cast_sign_loss,
- clippy::checked_conversions,
- clippy::float_cmp,
- clippy::manual_range_contains,
- clippy::similar_names,
- clippy::too_many_lines,
- clippy::unreadable_literal,
- clippy::unseparated_literal_suffix,
- clippy::wildcard_imports
-)]
#[path = "../src/common.rs"]
mod common;
-#[cfg(not(feature = "small"))]
#[path = "../src/d2s_full_table.rs"]
mod d2s_full_table;
#[path = "../src/d2s_intrinsics.rs"]
mod d2s_intrinsics;
-#[cfg(feature = "small")]
-#[path = "../src/d2s_small_table.rs"]
-mod d2s_small_table;
-
#[path = "../src/d2s.rs"]
mod d2s;
@@ -94,17 +74,4 @@ fn test_min_max() {
fn test_mantissa_rounding_overflow() {
assert_eq!(1.0, s2f(b"0.999999999").unwrap());
assert_eq!(f32::INFINITY, s2f(b"3.4028236e+38").unwrap());
- assert_eq!(1.1754944e-38, s2f(b"1.17549430e-38").unwrap()); // FLT_MIN
- assert_eq!(1.1754944e-38, s2f(b"1.17549431e-38").unwrap());
- assert_eq!(1.1754944e-38, s2f(b"1.17549432e-38").unwrap());
- assert_eq!(1.1754944e-38, s2f(b"1.17549433e-38").unwrap());
- assert_eq!(1.1754944e-38, s2f(b"1.17549434e-38").unwrap());
- assert_eq!(1.1754944e-38, s2f(b"1.17549435e-38").unwrap());
-}
-
-#[test]
-fn test_trailing_zeros() {
- assert_eq!(26843550.0, s2f(b"26843549.5").unwrap());
- assert_eq!(50000004.0, s2f(b"50000002.5").unwrap());
- assert_eq!(99999992.0, s2f(b"99999989.5").unwrap());
}