summaryrefslogtreecommitdiffstats
path: root/src/common/mod.rs
diff options
context:
space:
mode:
authorfdb-hiroshima <35889323+fdb-hiroshima@users.noreply.github.com>2019-07-27 10:57:33 +0200
committerPaul Masurel <paul.masurel@gmail.com>2019-07-27 17:57:33 +0900
commit6eb4e08636f48091f7783d52c84ef78e7ff1ada4 (patch)
tree2a91b898c007abfdf32e4261950a8625bc2749ca /src/common/mod.rs
parentc3231ca252da192e7e164b9b7474a6b99b85d7a7 (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.rs63
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);