Introduces a struct for xsd:float and xsd:double

Allows building XSD assumptions into it
pull/171/head
Tpt 3 years ago
parent dc1acd17a8
commit 1c7bec5226
  1. 24
      lib/src/model/literal.rs
  2. 61
      lib/src/model/xsd/decimal.rs
  3. 281
      lib/src/model/xsd/double.rs
  4. 253
      lib/src/model/xsd/float.rs
  5. 4
      lib/src/model/xsd/mod.rs
  6. 124
      lib/src/sparql/eval.rs
  7. 4
      lib/src/storage/binary_encoder.rs
  8. 37
      lib/src/storage/numeric_encoder.rs

@ -265,6 +265,13 @@ impl From<u16> for Literal {
impl From<f32> for Literal {
#[inline]
fn from(value: f32) -> Self {
Float::from(value).into()
}
}
impl From<Float> for Literal {
#[inline]
fn from(value: Float) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::FLOAT.into(),
@ -275,6 +282,13 @@ impl From<f32> for Literal {
impl From<f64> for Literal {
#[inline]
fn from(value: f64) -> Self {
Double::from(value).into()
}
}
impl From<Double> for Literal {
#[inline]
fn from(value: Double) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::DOUBLE.into(),
@ -621,4 +635,14 @@ mod tests {
LiteralRef::new_typed_literal("foo", xsd::STRING)
);
}
#[test]
fn test_float_format() {
assert_eq!("INF", Literal::from(f32::INFINITY).value());
assert_eq!("INF", Literal::from(f64::INFINITY).value());
assert_eq!("-INF", Literal::from(f32::NEG_INFINITY).value());
assert_eq!("-INF", Literal::from(f64::NEG_INFINITY).value());
assert_eq!("NaN", Literal::from(f32::NAN).value());
assert_eq!("NaN", Literal::from(f64::NAN).value());
}
}

@ -1,3 +1,5 @@
use crate::model::xsd::double::Double;
use crate::model::xsd::Float;
use std::convert::{TryFrom, TryInto};
use std::error::Error;
use std::fmt;
@ -85,12 +87,14 @@ impl Decimal {
}
/// TODO: XSD? is well defined for not integer
#[inline]
pub fn checked_rem(&self, rhs: impl Into<Self>) -> Option<Self> {
Some(Self {
value: self.value.checked_rem(rhs.into().value)?,
})
}
#[inline]
pub fn checked_rem_euclid(&self, rhs: impl Into<Self>) -> Option<Self> {
Some(Self {
value: self.value.checked_rem_euclid(rhs.into().value)?,
@ -142,59 +146,64 @@ impl Decimal {
}
}
#[inline]
pub const fn is_negative(&self) -> bool {
self.value < 0
}
#[inline]
pub const fn is_positive(&self) -> bool {
self.value > 0
}
/// Creates a `Decimal` from a `f32` without taking care of precision
/// Creates a `Decimal` from a `Float` without taking care of precision
#[inline]
pub(crate) fn from_f32(v: f32) -> Self {
Self::from_f64(v.into())
pub(crate) fn from_float(v: Float) -> Self {
Self::from_double(v.into())
}
/// Creates a `f32` from a `Decimal` without taking care of precision
/// Creates a `Float` from a `Decimal` without taking care of precision
#[inline]
#[allow(clippy::cast_possible_truncation)]
pub fn to_f32(self) -> f32 {
self.to_f64() as f32
pub fn to_float(self) -> Float {
(f64::from(self.to_double()) as f32).into()
}
/// Creates a `Decimal` from a `f64` without taking care of precision
/// Creates a `Decimal` from a `Double` without taking care of precision
#[inline]
#[allow(clippy::cast_possible_truncation, clippy::cast_precision_loss)]
pub(crate) fn from_f64(v: f64) -> Self {
pub(crate) fn from_double(v: Double) -> Self {
Self {
value: (v * (DECIMAL_PART_POW as f64)) as i128,
value: (f64::from(v) * (DECIMAL_PART_POW as f64)) as i128,
}
}
/// Creates a `f64` from a `Decimal` without taking care of precision
/// Creates a `Double` from a `Decimal` without taking care of precision
#[inline]
#[allow(clippy::cast_possible_truncation, clippy::cast_precision_loss)]
pub fn to_f64(self) -> f64 {
(self.value as f64) / (DECIMAL_PART_POW as f64)
pub fn to_double(self) -> Double {
((self.value as f64) / (DECIMAL_PART_POW as f64)).into()
}
/// Creates a `bool` from a `Decimal` according to xsd:boolean cast constraints
#[inline]
pub fn to_bool(self) -> bool {
self.value != 0
}
#[inline]
pub(super) const fn as_i128(&self) -> i128 {
self.value / DECIMAL_PART_POW
}
#[cfg(test)]
pub(super) const fn min_value() -> Self {
Self {
value: i128::min_value(),
}
Self { value: i128::MIN }
}
#[cfg(test)]
pub(super) const fn max_value() -> Self {
Self {
value: i128::max_value(),
}
Self { value: i128::MAX }
}
#[cfg(test)]
@ -211,49 +220,63 @@ impl From<i8> for Decimal {
}
}
}
impl From<i16> for Decimal {
#[inline]
fn from(value: i16) -> Self {
Self {
value: i128::from(value) * DECIMAL_PART_POW,
}
}
}
impl From<i32> for Decimal {
#[inline]
fn from(value: i32) -> Self {
Self {
value: i128::from(value) * DECIMAL_PART_POW,
}
}
}
impl From<i64> for Decimal {
#[inline]
fn from(value: i64) -> Self {
Self {
value: i128::from(value) * DECIMAL_PART_POW,
}
}
}
impl From<u8> for Decimal {
#[inline]
fn from(value: u8) -> Self {
Self {
value: i128::from(value) * DECIMAL_PART_POW,
}
}
}
impl From<u16> for Decimal {
#[inline]
fn from(value: u16) -> Self {
Self {
value: i128::from(value) * DECIMAL_PART_POW,
}
}
}
impl From<u32> for Decimal {
#[inline]
fn from(value: u32) -> Self {
Self {
value: i128::from(value) * DECIMAL_PART_POW,
}
}
}
impl From<u64> for Decimal {
#[inline]
fn from(value: u64) -> Self {
Self {
value: i128::from(value) * DECIMAL_PART_POW,
@ -264,6 +287,7 @@ impl From<u64> for Decimal {
impl TryFrom<i128> for Decimal {
type Error = DecimalOverflowError;
#[inline]
fn try_from(value: i128) -> Result<Self, DecimalOverflowError> {
Ok(Self {
value: value
@ -276,6 +300,7 @@ impl TryFrom<i128> for Decimal {
impl TryFrom<u128> for Decimal {
type Error = DecimalOverflowError;
#[inline]
fn try_from(value: u128) -> Result<Self, DecimalOverflowError> {
Ok(Self {
value: i128::try_from(value)

@ -0,0 +1,281 @@
use crate::model::xsd::Float;
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::num::ParseFloatError;
use std::ops::{Add, Div, Mul, Neg, Sub};
use std::str::FromStr;
/// [XML Schema `double` datatype](https://www.w3.org/TR/xmlschema11-2/#double) implementation.
///
/// The "==" implementation is identity, not equality
#[derive(Debug, Clone, Copy, Default)]
#[repr(transparent)]
pub struct Double {
value: f64,
}
impl Double {
#[inline]
pub fn from_be_bytes(bytes: [u8; 8]) -> Self {
Self {
value: f64::from_be_bytes(bytes),
}
}
#[inline]
pub fn to_be_bytes(self) -> [u8; 8] {
self.value.to_be_bytes()
}
/// [fn:abs](https://www.w3.org/TR/xpath-functions/#func-abs)
#[inline]
pub fn abs(self) -> Self {
self.value.abs().into()
}
/// [fn:ceiling](https://www.w3.org/TR/xpath-functions/#func-ceiling)
#[inline]
pub fn ceil(self) -> Self {
self.value.ceil().into()
}
/// [fn:floor](https://www.w3.org/TR/xpath-functions/#func-floor)
#[inline]
pub fn floor(self) -> Self {
self.value.floor().into()
}
/// [fn:round](https://www.w3.org/TR/xpath-functions/#func-round)
#[inline]
pub fn round(self) -> Self {
self.value.round().into()
}
/// Casts i64 into `Double`
#[inline]
#[allow(clippy::cast_precision_loss)]
pub fn from_i64(value: i64) -> Self {
Self {
value: value as f64,
}
}
/// Casts `Double` into i64 without taking care of loss
#[inline]
#[allow(clippy::cast_possible_truncation)]
pub fn to_i64(self) -> i64 {
self.value as i64
}
/// Casts `Double` into f32 without taking care of loss
#[inline]
#[allow(clippy::cast_possible_truncation)]
pub fn to_f32(self) -> f32 {
self.value as f32
}
/// Creates a `bool` from a `Decimal` according to xsd:boolean cast constraints
#[inline]
pub fn to_bool(self) -> bool {
self.value != 0. && !self.value.is_nan()
}
}
impl From<Double> for f64 {
#[inline]
fn from(value: Double) -> Self {
value.value
}
}
impl From<f64> for Double {
#[inline]
fn from(value: f64) -> Self {
Self { value }
}
}
impl From<i8> for Double {
#[inline]
fn from(value: i8) -> Self {
Self {
value: value.into(),
}
}
}
impl From<i16> for Double {
#[inline]
fn from(value: i16) -> Self {
Self {
value: value.into(),
}
}
}
impl From<i32> for Double {
#[inline]
fn from(value: i32) -> Self {
Self {
value: value.into(),
}
}
}
impl From<u8> for Double {
#[inline]
fn from(value: u8) -> Self {
Self {
value: value.into(),
}
}
}
impl From<u16> for Double {
#[inline]
fn from(value: u16) -> Self {
Self {
value: value.into(),
}
}
}
impl From<u32> for Double {
#[inline]
fn from(value: u32) -> Self {
Self {
value: value.into(),
}
}
}
impl From<Float> for Double {
#[inline]
fn from(value: Float) -> Self {
Self {
value: value.into(),
}
}
}
impl FromStr for Double {
type Err = ParseFloatError;
/// Parses decimals lexical mapping
#[inline]
fn from_str(input: &str) -> Result<Self, ParseFloatError> {
Ok(f64::from_str(input)?.into())
}
}
impl fmt::Display for Double {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.value == f64::INFINITY {
f.write_str("INF")
} else if self.value == f64::NEG_INFINITY {
f.write_str("-INF")
} else {
self.value.fmt(f)
}
}
}
impl PartialEq for Double {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.value.to_ne_bytes() == other.value.to_ne_bytes()
}
}
impl Eq for Double {}
impl PartialOrd for Double {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.value.partial_cmp(&other.value)
}
}
impl Hash for Double {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
state.write(&self.value.to_ne_bytes())
}
}
impl Neg for Double {
type Output = Self;
#[inline]
fn neg(self) -> Self {
(-self.value).into()
}
}
impl Add for Double {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
(self.value + rhs.value).into()
}
}
impl Sub for Double {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
(self.value - rhs.value).into()
}
}
impl Mul for Double {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self {
(self.value * rhs.value).into()
}
}
impl Div for Double {
type Output = Self;
#[inline]
fn div(self, rhs: Self) -> Self {
(self.value / rhs.value).into()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn eq() {
assert_eq!(Double::from(0_f64), Double::from(0_f64));
assert_eq!(Double::from(f64::NAN), Double::from(f64::NAN));
assert_ne!(Double::from(-0.), Double::from(0.));
}
#[test]
fn from_str() -> Result<(), ParseFloatError> {
assert_eq!(Double::from(f64::NAN), Double::from_str("NaN")?);
assert_eq!(Double::from(f64::INFINITY), Double::from_str("INF")?);
assert_eq!(Double::from(f64::INFINITY), Double::from_str("+INF")?);
assert_eq!(Double::from(f64::NEG_INFINITY), Double::from_str("-INF")?);
assert_eq!(Double::from(0.), Double::from_str("0.0E0")?);
assert_eq!(Double::from(-0.), Double::from_str("-0.0E0")?);
Ok(())
}
#[test]
fn to_string() {
assert_eq!("NaN", Double::from(f64::NAN).to_string());
assert_eq!("INF", Double::from(f64::INFINITY).to_string());
assert_eq!("-INF", Double::from(f64::NEG_INFINITY).to_string());
}
}

@ -0,0 +1,253 @@
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::num::ParseFloatError;
use std::ops::{Add, Div, Mul, Neg, Sub};
use std::str::FromStr;
/// [XML Schema `float` datatype](https://www.w3.org/TR/xmlschema11-2/#float) implementation.
///
/// The "==" implementation is identity, not equality
#[derive(Debug, Clone, Copy, Default)]
#[repr(transparent)]
pub struct Float {
value: f32,
}
impl Float {
#[inline]
pub fn from_be_bytes(bytes: [u8; 4]) -> Self {
Self {
value: f32::from_be_bytes(bytes),
}
}
#[inline]
pub fn to_be_bytes(self) -> [u8; 4] {
self.value.to_be_bytes()
}
/// [fn:abs](https://www.w3.org/TR/xpath-functions/#func-abs)
#[inline]
pub fn abs(self) -> Self {
self.value.abs().into()
}
/// [fn:ceiling](https://www.w3.org/TR/xpath-functions/#func-ceiling)
#[inline]
pub fn ceil(self) -> Self {
self.value.ceil().into()
}
/// [fn:floor](https://www.w3.org/TR/xpath-functions/#func-floor)
#[inline]
pub fn floor(self) -> Self {
self.value.floor().into()
}
/// [fn:round](https://www.w3.org/TR/xpath-functions/#func-round)
#[inline]
pub fn round(self) -> Self {
self.value.round().into()
}
/// Casts i64 into `Float`
#[inline]
#[allow(clippy::cast_precision_loss)]
pub fn from_i64(value: i64) -> Self {
Self {
value: value as f32,
}
}
/// Casts `Float` into i64 without taking care of loss
#[inline]
#[allow(clippy::cast_possible_truncation)]
pub fn to_i64(self) -> i64 {
self.value as i64
}
/// Creates a `bool` from a `Decimal` according to xsd:boolean cast constraints
#[inline]
pub fn to_bool(self) -> bool {
self.value != 0. && !self.value.is_nan()
}
}
impl From<Float> for f32 {
#[inline]
fn from(value: Float) -> Self {
value.value
}
}
impl From<Float> for f64 {
#[inline]
fn from(value: Float) -> Self {
value.value.into()
}
}
impl From<f32> for Float {
#[inline]
fn from(value: f32) -> Self {
Self { value }
}
}
impl From<i8> for Float {
#[inline]
fn from(value: i8) -> Self {
Self {
value: value.into(),
}
}
}
impl From<i16> for Float {
#[inline]
fn from(value: i16) -> Self {
Self {
value: value.into(),
}
}
}
impl From<u8> for Float {
#[inline]
fn from(value: u8) -> Self {
Self {
value: value.into(),
}
}
}
impl From<u16> for Float {
#[inline]
fn from(value: u16) -> Self {
Self {
value: value.into(),
}
}
}
impl FromStr for Float {
type Err = ParseFloatError;
/// Parses decimals lexical mapping
#[inline]
fn from_str(input: &str) -> Result<Self, ParseFloatError> {
Ok(f32::from_str(input)?.into())
}
}
impl fmt::Display for Float {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.value == f32::INFINITY {
f.write_str("INF")
} else if self.value == f32::NEG_INFINITY {
f.write_str("-INF")
} else {
self.value.fmt(f)
}
}
}
impl PartialEq for Float {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.value.to_ne_bytes() == other.value.to_ne_bytes()
}
}
impl Eq for Float {}
impl PartialOrd for Float {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.value.partial_cmp(&other.value)
}
}
impl Hash for Float {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
state.write(&self.value.to_ne_bytes())
}
}
impl Neg for Float {
type Output = Self;
#[inline]
fn neg(self) -> Self {
(-self.value).into()
}
}
impl Add for Float {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
(self.value + rhs.value).into()
}
}
impl Sub for Float {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
(self.value - rhs.value).into()
}
}
impl Mul for Float {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self {
(self.value * rhs.value).into()
}
}
impl Div for Float {
type Output = Self;
#[inline]
fn div(self, rhs: Self) -> Self {
(self.value / rhs.value).into()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn eq() {
assert_eq!(Float::from(0_f32), Float::from(0_f32));
assert_eq!(Float::from(f32::NAN), Float::from(f32::NAN));
assert_ne!(Float::from(-0.), Float::from(0.));
}
#[test]
fn from_str() -> Result<(), ParseFloatError> {
assert_eq!(Float::from(f32::NAN), Float::from_str("NaN")?);
assert_eq!(Float::from(f32::INFINITY), Float::from_str("INF")?);
assert_eq!(Float::from(f32::INFINITY), Float::from_str("+INF")?);
assert_eq!(Float::from(f32::NEG_INFINITY), Float::from_str("-INF")?);
assert_eq!(Float::from(0.), Float::from_str("0.0E0")?);
assert_eq!(Float::from(-0.), Float::from_str("-0.0E0")?);
Ok(())
}
#[test]
fn to_string() {
assert_eq!("NaN", Float::from(f32::NAN).to_string());
assert_eq!("INF", Float::from(f32::INFINITY).to_string());
assert_eq!("-INF", Float::from(f32::NEG_INFINITY).to_string());
}
}

@ -1,9 +1,13 @@
pub mod date_time;
pub mod decimal;
mod double;
mod duration;
mod float;
mod parser;
pub use self::date_time::{Date, DateTime, GDay, GMonth, GMonthDay, GYear, GYearMonth, Time};
pub use self::decimal::Decimal;
pub use self::double::Double;
pub use self::duration::{DayTimeDuration, Duration, YearMonthDuration};
pub use self::float::Float;
pub use self::parser::XsdParseError;

@ -1446,10 +1446,10 @@ impl SimpleEvaluator {
PlanExpression::IsTriple(e) => Some(self.eval_expression(e, tuple)?.is_triple().into()),
PlanExpression::BooleanCast(e) => match self.eval_expression(e, tuple)? {
EncodedTerm::BooleanLiteral(value) => Some(value.into()),
EncodedTerm::FloatLiteral(value) => Some((value != 0. && !value.is_nan()).into()),
EncodedTerm::DoubleLiteral(value) => Some((value != 0. && !value.is_nan()).into()),
EncodedTerm::FloatLiteral(value) => Some(value.to_bool().into()),
EncodedTerm::DoubleLiteral(value) => Some(value.to_bool().into()),
EncodedTerm::IntegerLiteral(value) => Some((value != 0).into()),
EncodedTerm::DecimalLiteral(value) => Some((value != Decimal::default()).into()),
EncodedTerm::DecimalLiteral(value) => Some(value.to_bool().into()),
EncodedTerm::SmallStringLiteral(value) => parse_boolean_str(&value),
EncodedTerm::BigStringLiteral { value_id } => {
parse_boolean_str(&*self.dataset.get_str(&value_id).ok()??)
@ -1460,7 +1460,7 @@ impl SimpleEvaluator {
EncodedTerm::FloatLiteral(value) => Some(f64::from(value).into()),
EncodedTerm::DoubleLiteral(value) => Some(value.into()),
EncodedTerm::IntegerLiteral(value) => Some((value as f64).into()),
EncodedTerm::DecimalLiteral(value) => Some(value.to_f64().into()),
EncodedTerm::DecimalLiteral(value) => Some(value.to_double().into()),
EncodedTerm::BooleanLiteral(value) => {
Some(if value { 1_f64 } else { 0_f64 }.into())
}
@ -1472,9 +1472,9 @@ impl SimpleEvaluator {
},
PlanExpression::FloatCast(e) => match self.eval_expression(e, tuple)? {
EncodedTerm::FloatLiteral(value) => Some(value.into()),
EncodedTerm::DoubleLiteral(value) => Some((value as f32).into()),
EncodedTerm::DoubleLiteral(value) => Some(value.to_f32().into()),
EncodedTerm::IntegerLiteral(value) => Some((value as f32).into()),
EncodedTerm::DecimalLiteral(value) => Some(value.to_f32().into()),
EncodedTerm::DecimalLiteral(value) => Some(value.to_float().into()),
EncodedTerm::BooleanLiteral(value) => {
Some(if value { 1_f32 } else { 0_f32 }.into())
}
@ -1485,8 +1485,8 @@ impl SimpleEvaluator {
_ => None,
},
PlanExpression::IntegerCast(e) => match self.eval_expression(e, tuple)? {
EncodedTerm::FloatLiteral(value) => Some((value as i64).into()),
EncodedTerm::DoubleLiteral(value) => Some((value as i64).into()),
EncodedTerm::FloatLiteral(value) => Some(value.to_i64().into()),
EncodedTerm::DoubleLiteral(value) => Some(value.to_i64().into()),
EncodedTerm::IntegerLiteral(value) => Some(value.into()),
EncodedTerm::DecimalLiteral(value) => Some(i64::try_from(value).ok()?.into()),
EncodedTerm::BooleanLiteral(value) => Some(if value { 1 } else { 0 }.into()),
@ -1497,8 +1497,8 @@ impl SimpleEvaluator {
_ => None,
},
PlanExpression::DecimalCast(e) => match self.eval_expression(e, tuple)? {
EncodedTerm::FloatLiteral(value) => Some(Decimal::from_f32(value).into()),
EncodedTerm::DoubleLiteral(value) => Some(Decimal::from_f64(value).into()),
EncodedTerm::FloatLiteral(value) => Some(Decimal::from_float(value).into()),
EncodedTerm::DoubleLiteral(value) => Some(Decimal::from_double(value).into()),
EncodedTerm::IntegerLiteral(value) => Some(Decimal::from(value).into()),
EncodedTerm::DecimalLiteral(value) => Some(value.into()),
EncodedTerm::BooleanLiteral(value) => {
@ -1579,8 +1579,8 @@ impl SimpleEvaluator {
EncodedTerm::BigStringLiteral { value_id } => {
Some(!self.dataset.get_str(value_id).ok()??.is_empty())
}
EncodedTerm::FloatLiteral(value) => Some(*value != 0_f32),
EncodedTerm::DoubleLiteral(value) => Some(*value != 0_f64),
EncodedTerm::FloatLiteral(value) => Some(*value != Float::default()),
EncodedTerm::DoubleLiteral(value) => Some(*value != Double::default()),
EncodedTerm::IntegerLiteral(value) => Some(*value != 0),
EncodedTerm::DecimalLiteral(value) => Some(*value != Decimal::default()),
_ => None,
@ -1913,31 +1913,31 @@ impl SimpleEvaluator {
},
EncodedTerm::FloatLiteral(a) => match b {
EncodedTerm::FloatLiteral(b) => Some(a == b),
EncodedTerm::DoubleLiteral(b) => Some(f64::from(*a) == *b),
EncodedTerm::IntegerLiteral(b) => Some(*a == *b as f32),
EncodedTerm::DecimalLiteral(b) => Some(*a == b.to_f32()),
EncodedTerm::DoubleLiteral(b) => Some(Double::from(*a) == *b),
EncodedTerm::IntegerLiteral(b) => Some(*a == Float::from_i64(*b)),
EncodedTerm::DecimalLiteral(b) => Some(*a == b.to_float()),
_ if b.is_unknown_typed_literal() => None,
_ => Some(false),
},
EncodedTerm::DoubleLiteral(a) => match b {
EncodedTerm::FloatLiteral(b) => Some(*a == f64::from(*b)),
EncodedTerm::FloatLiteral(b) => Some(*a == Double::from(*b)),
EncodedTerm::DoubleLiteral(b) => Some(a == b),
EncodedTerm::IntegerLiteral(b) => Some(*a == (*b as f64)),
EncodedTerm::DecimalLiteral(b) => Some(*a == b.to_f64()),
EncodedTerm::IntegerLiteral(b) => Some(*a == Double::from_i64(*b)),
EncodedTerm::DecimalLiteral(b) => Some(*a == b.to_double()),
_ if b.is_unknown_typed_literal() => None,
_ => Some(false),
},
EncodedTerm::IntegerLiteral(a) => match b {
EncodedTerm::FloatLiteral(b) => Some((*a as f32) == *b),
EncodedTerm::DoubleLiteral(b) => Some((*a as f64) == *b),
EncodedTerm::FloatLiteral(b) => Some(Float::from_i64(*a) == *b),
EncodedTerm::DoubleLiteral(b) => Some(Double::from_i64(*a) == *b),
EncodedTerm::IntegerLiteral(b) => Some(a == b),
EncodedTerm::DecimalLiteral(b) => Some(Decimal::from(*a) == *b),
_ if b.is_unknown_typed_literal() => None,
_ => Some(false),
},
EncodedTerm::DecimalLiteral(a) => match b {
EncodedTerm::FloatLiteral(b) => Some(a.to_f32() == *b),
EncodedTerm::DoubleLiteral(b) => Some(a.to_f64() == *b),
EncodedTerm::FloatLiteral(b) => Some(a.to_float() == *b),
EncodedTerm::DoubleLiteral(b) => Some(a.to_double() == *b),
EncodedTerm::IntegerLiteral(b) => Some(*a == Decimal::from(*b)),
EncodedTerm::DecimalLiteral(b) => Some(a == b),
_ if b.is_unknown_typed_literal() => None,
@ -2106,105 +2106,105 @@ impl SimpleEvaluator {
_ => None,
},
EncodedTerm::FloatLiteral(a) => match b {
EncodedTerm::FloatLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::DoubleLiteral(ref b) => f64::from(*a).partial_cmp(b),
EncodedTerm::IntegerLiteral(b) => a.partial_cmp(&((*b) as f32)),
EncodedTerm::DecimalLiteral(b) => a.partial_cmp(&b.to_f32()),
EncodedTerm::FloatLiteral(b) => a.partial_cmp(b),
EncodedTerm::DoubleLiteral(b) => Double::from(*a).partial_cmp(b),
EncodedTerm::IntegerLiteral(b) => a.partial_cmp(&Float::from_i64(*b)),
EncodedTerm::DecimalLiteral(b) => a.partial_cmp(&b.to_float()),
_ => None,
},
EncodedTerm::DoubleLiteral(a) => match b {
EncodedTerm::FloatLiteral(b) => a.partial_cmp(&(*b).into()),
EncodedTerm::DoubleLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::IntegerLiteral(b) => a.partial_cmp(&((*b) as f64)),
EncodedTerm::DecimalLiteral(b) => a.partial_cmp(&b.to_f64()),
EncodedTerm::DoubleLiteral(b) => a.partial_cmp(b),
EncodedTerm::IntegerLiteral(b) => a.partial_cmp(&Double::from_i64(*b)),
EncodedTerm::DecimalLiteral(b) => a.partial_cmp(&b.to_double()),
_ => None,
},
EncodedTerm::IntegerLiteral(a) => match b {
EncodedTerm::FloatLiteral(ref b) => ((*a) as f32).partial_cmp(b),
EncodedTerm::DoubleLiteral(ref b) => ((*a) as f64).partial_cmp(b),
EncodedTerm::IntegerLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::FloatLiteral(b) => Float::from_i64(*a).partial_cmp(b),
EncodedTerm::DoubleLiteral(b) => Double::from_i64(*a).partial_cmp(b),
EncodedTerm::IntegerLiteral(b) => a.partial_cmp(b),
EncodedTerm::DecimalLiteral(b) => Decimal::from(*a).partial_cmp(b),
_ => None,
},
EncodedTerm::DecimalLiteral(a) => match b {
EncodedTerm::FloatLiteral(ref b) => a.to_f32().partial_cmp(b),
EncodedTerm::DoubleLiteral(ref b) => a.to_f64().partial_cmp(b),
EncodedTerm::FloatLiteral(b) => a.to_float().partial_cmp(b),
EncodedTerm::DoubleLiteral(b) => a.to_double().partial_cmp(b),
EncodedTerm::IntegerLiteral(b) => a.partial_cmp(&Decimal::from(*b)),
EncodedTerm::DecimalLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::DecimalLiteral(b) => a.partial_cmp(b),
_ => None,
},
EncodedTerm::DateTimeLiteral(a) => {
if let EncodedTerm::DateTimeLiteral(ref b) = b {
if let EncodedTerm::DateTimeLiteral(b) = b {
a.partial_cmp(b)
} else {
None
}
}
EncodedTerm::TimeLiteral(a) => {
if let EncodedTerm::TimeLiteral(ref b) = b {
if let EncodedTerm::TimeLiteral(b) = b {
a.partial_cmp(b)
} else {
None
}
}
EncodedTerm::DateLiteral(a) => {
if let EncodedTerm::DateLiteral(ref b) = b {
if let EncodedTerm::DateLiteral(b) = b {
a.partial_cmp(b)
} else {
None
}
}
EncodedTerm::GYearMonthLiteral(a) => {
if let EncodedTerm::GYearMonthLiteral(ref b) = b {
if let EncodedTerm::GYearMonthLiteral(b) = b {
a.partial_cmp(b)
} else {
None
}
}
EncodedTerm::GYearLiteral(a) => {
if let EncodedTerm::GYearLiteral(ref b) = b {
if let EncodedTerm::GYearLiteral(b) = b {
a.partial_cmp(b)
} else {
None
}
}
EncodedTerm::GMonthDayLiteral(a) => {
if let EncodedTerm::GMonthDayLiteral(ref b) = b {
if let EncodedTerm::GMonthDayLiteral(b) = b {
a.partial_cmp(b)
} else {
None
}
}
EncodedTerm::GDayLiteral(a) => {
if let EncodedTerm::GDayLiteral(ref b) = b {
if let EncodedTerm::GDayLiteral(b) = b {
a.partial_cmp(b)
} else {
None
}
}
EncodedTerm::GMonthLiteral(a) => {
if let EncodedTerm::GMonthLiteral(ref b) = b {
if let EncodedTerm::GMonthLiteral(b) = b {
a.partial_cmp(b)
} else {
None
}
}
EncodedTerm::DurationLiteral(a) => match b {
EncodedTerm::DurationLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::YearMonthDurationLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::DayTimeDurationLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::DurationLiteral(b) => a.partial_cmp(b),
EncodedTerm::YearMonthDurationLiteral(b) => a.partial_cmp(b),
EncodedTerm::DayTimeDurationLiteral(b) => a.partial_cmp(b),
_ => None,
},
EncodedTerm::YearMonthDurationLiteral(a) => match b {
EncodedTerm::DurationLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::YearMonthDurationLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::DayTimeDurationLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::DurationLiteral(b) => a.partial_cmp(b),
EncodedTerm::YearMonthDurationLiteral(b) => a.partial_cmp(b),
EncodedTerm::DayTimeDurationLiteral(b) => a.partial_cmp(b),
_ => None,
},
EncodedTerm::DayTimeDurationLiteral(a) => match b {
EncodedTerm::DurationLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::YearMonthDurationLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::DayTimeDurationLiteral(ref b) => a.partial_cmp(b),
EncodedTerm::DurationLiteral(b) => a.partial_cmp(b),
EncodedTerm::YearMonthDurationLiteral(b) => a.partial_cmp(b),
EncodedTerm::DayTimeDurationLiteral(b) => a.partial_cmp(b),
_ => None,
},
_ => None,
@ -2281,8 +2281,8 @@ impl SimpleEvaluator {
}
enum NumericBinaryOperands {
Float(f32, f32),
Double(f64, f64),
Float(Float, Float),
Double(Double, Double),
Integer(i64, i64),
Decimal(Decimal, Decimal),
Duration(Duration, Duration),
@ -2312,10 +2312,10 @@ impl NumericBinaryOperands {
Some(Self::Double((*v1).into(), *v2))
}
(EncodedTerm::FloatLiteral(v1), EncodedTerm::IntegerLiteral(v2)) => {
Some(Self::Float(*v1, *v2 as f32))
Some(Self::Float(*v1, Float::from_i64(*v2)))
}
(EncodedTerm::FloatLiteral(v1), EncodedTerm::DecimalLiteral(v2)) => {
Some(Self::Float(*v1, v2.to_f32()))
Some(Self::Float(*v1, v2.to_float()))
}
(EncodedTerm::DoubleLiteral(v1), EncodedTerm::FloatLiteral(v2)) => {
Some(Self::Double(*v1, (*v2).into()))
@ -2324,16 +2324,16 @@ impl NumericBinaryOperands {
Some(Self::Double(*v1, *v2))
}
(EncodedTerm::DoubleLiteral(v1), EncodedTerm::IntegerLiteral(v2)) => {
Some(Self::Double(*v1, *v2 as f64))
Some(Self::Double(*v1, Double::from_i64(*v2)))
}
(EncodedTerm::DoubleLiteral(v1), EncodedTerm::DecimalLiteral(v2)) => {
Some(Self::Double(*v1, v2.to_f64()))
Some(Self::Double(*v1, v2.to_double()))
}
(EncodedTerm::IntegerLiteral(v1), EncodedTerm::FloatLiteral(v2)) => {
Some(Self::Float(*v1 as f32, *v2))
Some(Self::Float(Float::from_i64(*v1), *v2))
}
(EncodedTerm::IntegerLiteral(v1), EncodedTerm::DoubleLiteral(v2)) => {
Some(Self::Double(*v1 as f64, *v2))
Some(Self::Double(Double::from_i64(*v1), *v2))
}
(EncodedTerm::IntegerLiteral(v1), EncodedTerm::IntegerLiteral(v2)) => {
Some(Self::Integer(*v1, *v2))
@ -2342,10 +2342,10 @@ impl NumericBinaryOperands {
Some(Self::Decimal(Decimal::from(*v1), *v2))
}
(EncodedTerm::DecimalLiteral(v1), EncodedTerm::FloatLiteral(v2)) => {
Some(Self::Float(v1.to_f32(), *v2))
Some(Self::Float(v1.to_float(), *v2))
}
(EncodedTerm::DecimalLiteral(v1), EncodedTerm::DoubleLiteral(v2)) => {
Some(Self::Double(v1.to_f64(), *v2))
Some(Self::Double(v1.to_double(), *v2))
}
(EncodedTerm::DecimalLiteral(v1), EncodedTerm::IntegerLiteral(v2)) => {
Some(Self::Decimal(*v1, Decimal::from(*v2)))

@ -315,12 +315,12 @@ impl<R: Read> TermReader for R {
TYPE_FLOAT_LITERAL => {
let mut buffer = [0; 4];
self.read_exact(&mut buffer)?;
Ok(EncodedTerm::FloatLiteral(f32::from_be_bytes(buffer)))
Ok(EncodedTerm::FloatLiteral(Float::from_be_bytes(buffer)))
}
TYPE_DOUBLE_LITERAL => {
let mut buffer = [0; 8];
self.read_exact(&mut buffer)?;
Ok(EncodedTerm::DoubleLiteral(f64::from_be_bytes(buffer)))
Ok(EncodedTerm::DoubleLiteral(Double::from_be_bytes(buffer)))
}
TYPE_INTEGER_LITERAL => {
let mut buffer = [0; 8];

@ -84,8 +84,8 @@ pub enum EncodedTerm {
datatype_id: StrHash,
},
BooleanLiteral(bool),
FloatLiteral(f32),
DoubleLiteral(f64),
FloatLiteral(Float),
DoubleLiteral(Double),
IntegerLiteral(i64),
DecimalLiteral(Decimal),
DateTimeLiteral(DateTime),
@ -186,20 +186,8 @@ impl PartialEq for EncodedTerm {
},
) => value_id_a == value_id_b && datatype_id_a == datatype_id_b,
(Self::BooleanLiteral(a), Self::BooleanLiteral(b)) => a == b,
(Self::FloatLiteral(a), Self::FloatLiteral(b)) => {
if a.is_nan() {
b.is_nan()
} else {
a == b
}
}
(Self::DoubleLiteral(a), Self::DoubleLiteral(b)) => {
if a.is_nan() {
b.is_nan()
} else {
a == b
}
}
(Self::FloatLiteral(a), Self::FloatLiteral(b)) => a == b,
(Self::DoubleLiteral(a), Self::DoubleLiteral(b)) => a == b,
(Self::IntegerLiteral(a), Self::IntegerLiteral(b)) => a == b,
(Self::DecimalLiteral(a), Self::DecimalLiteral(b)) => a == b,
(Self::DateTimeLiteral(a), Self::DateTimeLiteral(b)) => a.is_identical_with(b),
@ -262,8 +250,8 @@ impl Hash for EncodedTerm {
datatype_id.hash(state);
}
Self::BooleanLiteral(value) => value.hash(state),
Self::FloatLiteral(value) => state.write(&value.to_ne_bytes()),
Self::DoubleLiteral(value) => state.write(&value.to_ne_bytes()),
Self::FloatLiteral(value) => value.hash(state),
Self::DoubleLiteral(value) => value.hash(state),
Self::IntegerLiteral(value) => value.hash(state),
Self::DecimalLiteral(value) => value.hash(state),
Self::DateTimeLiteral(value) => value.hash(state),
@ -371,14 +359,27 @@ impl From<u8> for EncodedTerm {
Self::IntegerLiteral(value.into())
}
}
impl From<f32> for EncodedTerm {
fn from(value: f32) -> Self {
Self::FloatLiteral(value.into())
}
}
impl From<Float> for EncodedTerm {
fn from(value: Float) -> Self {
Self::FloatLiteral(value)
}
}
impl From<f64> for EncodedTerm {
fn from(value: f64) -> Self {
Self::DoubleLiteral(value.into())
}
}
impl From<Double> for EncodedTerm {
fn from(value: Double) -> Self {
Self::DoubleLiteral(value)
}
}

Loading…
Cancel
Save