From a4f33d3823f1bad3ff7a59877f1608615acabe6e Mon Sep 17 00:00:00 2001 From: Paul Masurel Date: Tue, 15 Dec 2020 13:40:31 +0900 Subject: [PATCH] Added comment to f64 conversion to u64. - Added proptest - Added comment to Lemire blog post. --- src/common/mod.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/common/mod.rs b/src/common/mod.rs index 1dcb98afa..45bee6a59 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -115,11 +115,16 @@ pub fn u64_to_i64(val: u64) -> i64 { /// For simplicity, tantivy internally handles `f64` as `u64`. /// The mapping is defined by this function. /// -/// Maps `f64` to `u64` so that lexical order is preserved. +/// Maps `f64` to `u64` in a monotonic manner, so that bytes lexical order is preserved. /// /// This is more suited than simply casting (`val as u64`) /// which would truncate the result /// +/// # Reference +/// +/// Daniel Lemire's [blog post](https://lemire.me/blog/2020/12/14/converting-floating-point-numbers-to-integers-while-preserving-order/) +/// explains the mapping in a clear manner. +/// /// # See also /// The [reverse mapping is `u64_to_f64`](./fn.u64_to_f64.html). #[inline(always)] @@ -148,6 +153,7 @@ pub(crate) mod test { pub use super::minmax; pub use super::serialize::test::fixed_size_test; use super::{compute_num_bits, f64_to_u64, i64_to_u64, u64_to_f64, u64_to_i64}; + use proptest::prelude::*; use std::f64; fn test_i64_converter_helper(val: i64) { @@ -158,6 +164,15 @@ pub(crate) mod test { assert_eq!(u64_to_f64(f64_to_u64(val)), val); } + proptest! { + #[test] + fn test_f64_converter_monotonicity_proptest((left, right) in (proptest::num::f64::NORMAL, proptest::num::f64::NORMAL)) { + let left_u64 = f64_to_u64(left); + let right_u64 = f64_to_u64(right); + assert_eq!(left_u64 < right_u64, left < right); + } + } + #[test] fn test_i64_converter() { assert_eq!(i64_to_u64(i64::min_value()), u64::min_value());