diff options
author | fdb-hiroshima <35889323+fdb-hiroshima@users.noreply.github.com> | 2019-07-27 10:57:33 +0200 |
---|---|---|
committer | Paul Masurel <paul.masurel@gmail.com> | 2019-07-27 17:57:33 +0900 |
commit | 6eb4e08636f48091f7783d52c84ef78e7ff1ada4 (patch) | |
tree | 2a91b898c007abfdf32e4261950a8625bc2749ca /src/common/mod.rs | |
parent | c3231ca252da192e7e164b9b7474a6b99b85d7a7 (diff) |
add support for float (#603)
* add basic support for float
as for i64, they are mapped to u64 for indexing
query parser don't work yet
* Update value.rs
* implement support for float in query parser
* Update README.md
Diffstat (limited to 'src/common/mod.rs')
-rw-r--r-- | src/common/mod.rs | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/src/common/mod.rs b/src/common/mod.rs index 8f6deaf..7e41f08 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -99,15 +99,54 @@ pub fn u64_to_i64(val: u64) -> i64 { (val ^ HIGHEST_BIT) as i64 } +/// Maps a `f64` to `u64` +/// +/// 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. +/// +/// This is more suited than simply casting (`val as u64`) +/// which would truncate the result +/// +/// # See also +/// The [reverse mapping is `u64_to_f64`](./fn.u64_to_f64.html). +#[inline(always)] +pub fn f64_to_u64(val: f64) -> u64 { + let bits = val.to_bits(); + if val.is_sign_positive() { + bits ^ HIGHEST_BIT + } else { + !bits + } +} + +/// Reverse the mapping given by [`i64_to_u64`](./fn.i64_to_u64.html). +#[inline(always)] +pub fn u64_to_f64(val: u64) -> f64 { + f64::from_bits( + if val & HIGHEST_BIT != 0 { + val ^ HIGHEST_BIT + } else { + !val + } + ) +} + #[cfg(test)] pub(crate) mod test { pub use super::serialize::test::fixed_size_test; - use super::{compute_num_bits, i64_to_u64, u64_to_i64}; + use super::{compute_num_bits, i64_to_u64, u64_to_i64, f64_to_u64, u64_to_f64}; + use std::f64; fn test_i64_converter_helper(val: i64) { assert_eq!(u64_to_i64(i64_to_u64(val)), val); } + + fn test_f64_converter_helper(val: f64) { + assert_eq!(u64_to_f64(f64_to_u64(val)), val); + } #[test] fn test_i64_converter() { @@ -122,6 +161,28 @@ pub(crate) mod test { } #[test] + fn test_f64_converter() { + test_f64_converter_helper(f64::INFINITY); + test_f64_converter_helper(f64::NEG_INFINITY); + test_f64_converter_helper(0.0); + test_f64_converter_helper(-0.0); + test_f64_converter_helper(1.0); + test_f64_converter_helper(-1.0); + } + + #[test] + fn test_f64_order() { + assert!(!(f64_to_u64(f64::NEG_INFINITY)..f64_to_u64(f64::INFINITY)).contains(&f64_to_u64(f64::NAN))); //nan is not a number + assert!(f64_to_u64(1.5) > f64_to_u64(1.0)); //same exponent, different mantissa + assert!(f64_to_u64(2.0) > f64_to_u64(1.0)); //same mantissa, different exponent + assert!(f64_to_u64(2.0) > f64_to_u64(1.5)); //different exponent and mantissa + assert!(f64_to_u64(1.0) > f64_to_u64(-1.0)); // pos > neg + assert!(f64_to_u64(-1.5) < f64_to_u64(-1.0)); + assert!(f64_to_u64(-2.0) < f64_to_u64(1.0)); + assert!(f64_to_u64(-2.0) < f64_to_u64(-1.5)); + } + + #[test] fn test_compute_num_bits() { assert_eq!(compute_num_bits(1), 1u8); assert_eq!(compute_num_bits(0), 0u8); |