From 62a4fe5606a3c0fb401912075b1ca868c0fa4a66 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Mon, 6 Feb 2023 21:48:59 +0800 Subject: [PATCH] Handle NaN --- src/value.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/value.rs b/src/value.rs index d19b0ddcd..ab83efa3f 100644 --- a/src/value.rs +++ b/src/value.rs @@ -118,7 +118,10 @@ pub enum ArrayType { /// Value variants /// -/// We want Value to be exactly 1 pointer sized, so anything larger should be boxed. +/// We want the inner Value to be exactly 1 pointer sized, so anything larger should be boxed. +/// +/// If the `hashable-value` feature is enabled, NaN == NaN, which contradicts Rust's built-in +/// implementation of NaN != NaN. #[derive(Clone, Debug)] #[cfg_attr(not(feature = "hashable-value"), derive(PartialEq))] #[cfg_attr( @@ -1911,38 +1914,34 @@ mod tests { #[cfg(feature = "hashable-value")] mod hashable_value { use super::*; - use ordered_float::{NotNan, OrderedFloat}; + use ordered_float::OrderedFloat; use std::hash::{Hash, Hasher}; - /// Panic when value is NaN pub fn hash_f32(v: &Option, state: &mut H) { match v { - Some(v) => NotNan::new(*v).unwrap().hash(state), - None => OrderedFloat(std::f32::NAN).hash(state), + Some(v) => OrderedFloat(*v).hash(state), + None => "null".hash(state), } } - /// Panic when value is NaN pub fn hash_f64(v: &Option, state: &mut H) { match v { - Some(v) => NotNan::new(*v).unwrap().hash(state), - None => OrderedFloat(std::f64::NAN).hash(state), + Some(v) => OrderedFloat(*v).hash(state), + None => "null".hash(state), } } - /// Panic when value is NaN pub fn cmp_f32(l: &Option, r: &Option) -> bool { match (l, r) { - (Some(l), Some(r)) => NotNan::new(*l).unwrap().eq(&NotNan::new(*r).unwrap()), + (Some(l), Some(r)) => OrderedFloat(*l).eq(&OrderedFloat(*r)), (None, None) => true, _ => false, } } - /// Panic when value is NaN pub fn cmp_f64(l: &Option, r: &Option) -> bool { match (l, r) { - (Some(l), Some(r)) => NotNan::new(*l).unwrap().eq(&NotNan::new(*r).unwrap()), + (Some(l), Some(r)) => OrderedFloat(*l).eq(&OrderedFloat(*r)), (None, None) => true, _ => false, } @@ -1978,6 +1977,8 @@ mod hashable_value { Value::Float(None), Value::Double(None), Value::Double(None), + Value::Float(Some(std::f32::NAN)), // NaN considered equal + Value::Float(Some(std::f32::NAN)), ] .into_iter() .collect(); @@ -1987,6 +1988,7 @@ mod hashable_value { Value::BigInt(None), Value::Float(None), Value::Double(None), + Value::Float(Some(std::f32::NAN)), ] .into_iter() .collect();