From 6fa97e11bb8f86a5d1125871dc9194f46191f0a9 Mon Sep 17 00:00:00 2001 From: berkaysynnada Date: Thu, 12 Oct 2023 11:33:35 +0300 Subject: [PATCH 1/4] Sharpness enum is introduced. --- datafusion/common/src/stats.rs | 179 ++++++++++++++++++++++++++++++++- 1 file changed, 176 insertions(+), 3 deletions(-) diff --git a/datafusion/common/src/stats.rs b/datafusion/common/src/stats.rs index ca76e14cb8ab..2a54016e111c 100644 --- a/datafusion/common/src/stats.rs +++ b/datafusion/common/src/stats.rs @@ -17,11 +17,184 @@ //! This module provides data structures to represent statistics -use std::fmt::Display; - +use crate::ScalarValue; use arrow::datatypes::DataType; -use crate::ScalarValue; +use std::fmt::{self, Debug, Display}; + +/// To deal with information without exactness guarantees, we wrap it inside a +/// [`Sharpness`] object to express its reliability. +#[derive(Clone, PartialEq, Eq, Default)] +pub enum Sharpness { + Exact(T), + Inexact(T), + #[default] + Absent, +} + +impl Sharpness { + /// If we have some value (exact or inexact), it returns that value. + /// Otherwise, it returns `None`. + pub fn get_value(&self) -> Option<&T> { + match self { + Sharpness::Exact(value) | Sharpness::Inexact(value) => Some(value), + Sharpness::Absent => None, + } + } + + /// Transform the value in this [`Sharpness`] object, if one exists, using + /// the given function. Preserves the exactness state. + pub fn map(self, f: F) -> Sharpness + where + F: Fn(T) -> T, + { + match self { + Sharpness::Exact(val) => Sharpness::Exact(f(val)), + Sharpness::Inexact(val) => Sharpness::Inexact(f(val)), + _ => self, + } + } + + /// Returns `Some(true)` if we have an exact value, `Some(false)` if we + /// have an inexact value, and `None` if there is no value. + pub fn is_exact(&self) -> Option { + match self { + Sharpness::Exact(_) => Some(true), + Sharpness::Inexact(_) => Some(false), + _ => None, + } + } + + /// Returns the maximum of two (possibly inexact) values, conservatively + /// propagating exactness information. If one of the input values is + /// [`Sharpness::Absent`], the result is `Absent` too. + pub fn max(&self, other: &Sharpness) -> Sharpness { + match (self, other) { + (Sharpness::Exact(a), Sharpness::Exact(b)) => { + Sharpness::Exact(if a >= b { a.clone() } else { b.clone() }) + } + (Sharpness::Inexact(a), Sharpness::Exact(b)) + | (Sharpness::Exact(a), Sharpness::Inexact(b)) + | (Sharpness::Inexact(a), Sharpness::Inexact(b)) => { + Sharpness::Inexact(if a >= b { a.clone() } else { b.clone() }) + } + (_, _) => Sharpness::Absent, + } + } + + /// Returns the minimum of two (possibly inexact) values, conservatively + /// propagating exactness information. If one of the input values is + /// [`Sharpness::Absent`], the result is `Absent` too. + pub fn min(&self, other: &Sharpness) -> Sharpness { + match (self, other) { + (Sharpness::Exact(a), Sharpness::Exact(b)) => { + Sharpness::Exact(if a >= b { b.clone() } else { a.clone() }) + } + (Sharpness::Inexact(a), Sharpness::Exact(b)) + | (Sharpness::Exact(a), Sharpness::Inexact(b)) + | (Sharpness::Inexact(a), Sharpness::Inexact(b)) => { + Sharpness::Inexact(if a >= b { b.clone() } else { a.clone() }) + } + (_, _) => Sharpness::Absent, + } + } + + /// Demotes the sharpness state to inexact (if present). + pub fn to_inexact(self) -> Self { + match self { + Sharpness::Exact(value) => Sharpness::Inexact(value), + _ => self, + } + } +} + +impl Sharpness { + /// Calculates the sum of two (possibly inexact) [`usize`] values, + /// conservatively propagating exactness information. If one of the input + /// values is [`Sharpness::Absent`], the result is `Absent` too. + pub fn add(&self, other: &Sharpness) -> Sharpness { + match (self, other) { + (Sharpness::Exact(a), Sharpness::Exact(b)) => Sharpness::Exact(a + b), + (Sharpness::Inexact(a), Sharpness::Exact(b)) + | (Sharpness::Exact(a), Sharpness::Inexact(b)) + | (Sharpness::Inexact(a), Sharpness::Inexact(b)) => Sharpness::Inexact(a + b), + (_, _) => Sharpness::Absent, + } + } + + /// Calculates the difference of two (possibly inexact) [`usize`] values, + /// conservatively propagating exactness information. If one of the input + /// values is [`Sharpness::Absent`], the result is `Absent` too. + pub fn sub(&self, other: &Sharpness) -> Sharpness { + match (self, other) { + (Sharpness::Exact(a), Sharpness::Exact(b)) => Sharpness::Exact(a - b), + (Sharpness::Inexact(a), Sharpness::Exact(b)) + | (Sharpness::Exact(a), Sharpness::Inexact(b)) + | (Sharpness::Inexact(a), Sharpness::Inexact(b)) => Sharpness::Inexact(a - b), + (_, _) => Sharpness::Absent, + } + } + + /// Calculates the multiplication of two (possibly inexact) [`usize`] values, + /// conservatively propagating exactness information. If one of the input + /// values is [`Sharpness::Absent`], the result is `Absent` too. + pub fn multiply(&self, other: &Sharpness) -> Sharpness { + match (self, other) { + (Sharpness::Exact(a), Sharpness::Exact(b)) => Sharpness::Exact(a * b), + (Sharpness::Inexact(a), Sharpness::Exact(b)) + | (Sharpness::Exact(a), Sharpness::Inexact(b)) + | (Sharpness::Inexact(a), Sharpness::Inexact(b)) => Sharpness::Inexact(a * b), + (_, _) => Sharpness::Absent, + } + } +} + +impl Sharpness { + /// Calculates the sum of two (possibly inexact) [`ScalarValue`] values, + /// conservatively propagating exactness information. If one of the input + /// values is [`Sharpness::Absent`], the result is `Absent` too. + pub fn add(&self, other: &Sharpness) -> Sharpness { + match (self, other) { + (Sharpness::Exact(a), Sharpness::Exact(b)) => { + if let Ok(result) = a.add(b) { + Sharpness::Exact(result) + } else { + Sharpness::Absent + } + } + (Sharpness::Inexact(a), Sharpness::Exact(b)) + | (Sharpness::Exact(a), Sharpness::Inexact(b)) + | (Sharpness::Inexact(a), Sharpness::Inexact(b)) => { + if let Ok(result) = a.add(b) { + Sharpness::Inexact(result) + } else { + Sharpness::Absent + } + } + (_, _) => Sharpness::Absent, + } + } +} + +impl Debug for Sharpness { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Sharpness::Exact(inner) => write!(f, "Exact({:?})", inner), + Sharpness::Inexact(inner) => write!(f, "Inexact({:?})", inner), + Sharpness::Absent => write!(f, "Absent"), + } + } +} + +impl Display for Sharpness { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Sharpness::Exact(inner) => write!(f, "Exact({:?})", inner), + Sharpness::Inexact(inner) => write!(f, "Inexact({:?})", inner), + Sharpness::Absent => write!(f, "Absent"), + } + } +} /// Statistics for a relation /// Fields are optional and can be inexact because the sources From dd16b532a4e855a7dbf3fc1985c381090bba06a3 Mon Sep 17 00:00:00 2001 From: berkaysynnada Date: Thu, 12 Oct 2023 11:56:26 +0300 Subject: [PATCH 2/4] Unit tests added --- datafusion/common/src/stats.rs | 115 +++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/datafusion/common/src/stats.rs b/datafusion/common/src/stats.rs index 2a54016e111c..d163d784d63c 100644 --- a/datafusion/common/src/stats.rs +++ b/datafusion/common/src/stats.rs @@ -267,3 +267,118 @@ impl ColumnStatistics { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get_value() { + let exact_sharpness = Sharpness::Exact(42); + let inexact_sharpness = Sharpness::Inexact(23); + let absent_sharpness = Sharpness::::Absent; + + assert_eq!(*exact_sharpness.get_value().unwrap(), 42); + assert_eq!(*inexact_sharpness.get_value().unwrap(), 23); + assert_eq!(absent_sharpness.get_value(), None); + } + + #[test] + fn test_map() { + let exact_sharpness = Sharpness::Exact(42); + let inexact_sharpness = Sharpness::Inexact(23); + let absent_sharpness = Sharpness::Absent; + + let squared = |x| x * x; + + assert_eq!(exact_sharpness.map(squared), Sharpness::Exact(1764)); + assert_eq!(inexact_sharpness.map(squared), Sharpness::Inexact(529)); + assert_eq!(absent_sharpness.map(squared), Sharpness::Absent); + } + + #[test] + fn test_is_exact() { + let exact_sharpness = Sharpness::Exact(42); + let inexact_sharpness = Sharpness::Inexact(23); + let absent_sharpness = Sharpness::::Absent; + + assert_eq!(exact_sharpness.is_exact(), Some(true)); + assert_eq!(inexact_sharpness.is_exact(), Some(false)); + assert_eq!(absent_sharpness.is_exact(), None); + } + + #[test] + fn test_max() { + let sharpness1 = Sharpness::Exact(42); + let sharpness2 = Sharpness::Inexact(23); + let sharpness3 = Sharpness::Exact(30); + let absent_sharpness = Sharpness::Absent; + + assert_eq!(sharpness1.max(&sharpness2), Sharpness::Inexact(42)); + assert_eq!(sharpness1.max(&sharpness3), Sharpness::Exact(42)); + assert_eq!(sharpness2.max(&sharpness3), Sharpness::Inexact(30)); + assert_eq!(sharpness1.max(&absent_sharpness), Sharpness::Absent); + } + + #[test] + fn test_min() { + let sharpness1 = Sharpness::Exact(42); + let sharpness2 = Sharpness::Inexact(23); + let sharpness3 = Sharpness::Exact(30); + let absent_sharpness = Sharpness::Absent; + + assert_eq!(sharpness1.min(&sharpness2), Sharpness::Inexact(23)); + assert_eq!(sharpness1.min(&sharpness3), Sharpness::Exact(30)); + assert_eq!(sharpness2.min(&sharpness3), Sharpness::Inexact(23)); + assert_eq!(sharpness1.min(&absent_sharpness), Sharpness::Absent); + } + + #[test] + fn test_to_inexact() { + let exact_sharpness = Sharpness::Exact(42); + let inexact_sharpness = Sharpness::Inexact(23); + let absent_sharpness = Sharpness::::Absent; + + assert_eq!(exact_sharpness.clone().to_inexact(), inexact_sharpness); + assert_eq!(inexact_sharpness.clone().to_inexact(), inexact_sharpness); + assert_eq!(absent_sharpness.clone().to_inexact(), absent_sharpness); + } + + #[test] + fn test_add() { + let sharpness1 = Sharpness::Exact(42); + let sharpness2 = Sharpness::Inexact(23); + let sharpness3 = Sharpness::Exact(30); + let absent_sharpness = Sharpness::Absent; + + assert_eq!(sharpness1.add(&sharpness2), Sharpness::Inexact(65)); + assert_eq!(sharpness1.add(&sharpness3), Sharpness::Exact(72)); + assert_eq!(sharpness2.add(&sharpness3), Sharpness::Inexact(53)); + assert_eq!(sharpness1.add(&absent_sharpness), Sharpness::Absent); + } + + #[test] + fn test_sub() { + let sharpness1 = Sharpness::Exact(42); + let sharpness2 = Sharpness::Inexact(23); + let sharpness3 = Sharpness::Exact(30); + let absent_sharpness = Sharpness::Absent; + + assert_eq!(sharpness1.sub(&sharpness2), Sharpness::Inexact(19)); + assert_eq!(sharpness1.sub(&sharpness3), Sharpness::Exact(12)); + assert_eq!(sharpness1.sub(&absent_sharpness), Sharpness::Absent); + } + + #[test] + fn test_multiply() { + let sharpness1 = Sharpness::Exact(6); + let sharpness2 = Sharpness::Inexact(3); + let sharpness3 = Sharpness::Exact(5); + let absent_sharpness = Sharpness::Absent; + + assert_eq!(sharpness1.multiply(&sharpness2), Sharpness::Inexact(18)); + assert_eq!(sharpness1.multiply(&sharpness3), Sharpness::Exact(30)); + assert_eq!(sharpness2.multiply(&sharpness3), Sharpness::Inexact(15)); + assert_eq!(sharpness1.multiply(&absent_sharpness), Sharpness::Absent); + } +} From 81df49baa8561e0dd91abace9bf774de7cdd709f Mon Sep 17 00:00:00 2001 From: berkaysynnada Date: Thu, 12 Oct 2023 13:21:37 +0300 Subject: [PATCH 3/4] typo fix --- datafusion/common/src/stats.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datafusion/common/src/stats.rs b/datafusion/common/src/stats.rs index d163d784d63c..757a7dd57f67 100644 --- a/datafusion/common/src/stats.rs +++ b/datafusion/common/src/stats.rs @@ -336,7 +336,7 @@ mod tests { #[test] fn test_to_inexact() { let exact_sharpness = Sharpness::Exact(42); - let inexact_sharpness = Sharpness::Inexact(23); + let inexact_sharpness = Sharpness::Inexact(42); let absent_sharpness = Sharpness::::Absent; assert_eq!(exact_sharpness.clone().to_inexact(), inexact_sharpness); From 0a21aac6401a0f160e99aaebe1dce38d2323e645 Mon Sep 17 00:00:00 2001 From: berkaysynnada Date: Thu, 12 Oct 2023 16:53:34 +0300 Subject: [PATCH 4/4] Name changes to precision. --- datafusion/common/src/stats.rs | 287 +++++++++++++++++---------------- 1 file changed, 145 insertions(+), 142 deletions(-) diff --git a/datafusion/common/src/stats.rs b/datafusion/common/src/stats.rs index 757a7dd57f67..279ad434a817 100644 --- a/datafusion/common/src/stats.rs +++ b/datafusion/common/src/stats.rs @@ -22,35 +22,38 @@ use arrow::datatypes::DataType; use std::fmt::{self, Debug, Display}; -/// To deal with information without exactness guarantees, we wrap it inside a -/// [`Sharpness`] object to express its reliability. +/// Represents a value with a degree of certainty. `Precision` is used to +/// propagate information the precision of statistical values. #[derive(Clone, PartialEq, Eq, Default)] -pub enum Sharpness { +pub enum Precision { + /// The exact value is known Exact(T), + /// The value is not known exactly, but is likely close to this value Inexact(T), + /// Nothing is known about the value #[default] Absent, } -impl Sharpness { +impl Precision { /// If we have some value (exact or inexact), it returns that value. /// Otherwise, it returns `None`. pub fn get_value(&self) -> Option<&T> { match self { - Sharpness::Exact(value) | Sharpness::Inexact(value) => Some(value), - Sharpness::Absent => None, + Precision::Exact(value) | Precision::Inexact(value) => Some(value), + Precision::Absent => None, } } - /// Transform the value in this [`Sharpness`] object, if one exists, using + /// Transform the value in this [`Precision`] object, if one exists, using /// the given function. Preserves the exactness state. - pub fn map(self, f: F) -> Sharpness + pub fn map(self, f: F) -> Precision where F: Fn(T) -> T, { match self { - Sharpness::Exact(val) => Sharpness::Exact(f(val)), - Sharpness::Inexact(val) => Sharpness::Inexact(f(val)), + Precision::Exact(val) => Precision::Exact(f(val)), + Precision::Inexact(val) => Precision::Inexact(f(val)), _ => self, } } @@ -59,139 +62,139 @@ impl Sharpness { /// have an inexact value, and `None` if there is no value. pub fn is_exact(&self) -> Option { match self { - Sharpness::Exact(_) => Some(true), - Sharpness::Inexact(_) => Some(false), + Precision::Exact(_) => Some(true), + Precision::Inexact(_) => Some(false), _ => None, } } /// Returns the maximum of two (possibly inexact) values, conservatively /// propagating exactness information. If one of the input values is - /// [`Sharpness::Absent`], the result is `Absent` too. - pub fn max(&self, other: &Sharpness) -> Sharpness { + /// [`Precision::Absent`], the result is `Absent` too. + pub fn max(&self, other: &Precision) -> Precision { match (self, other) { - (Sharpness::Exact(a), Sharpness::Exact(b)) => { - Sharpness::Exact(if a >= b { a.clone() } else { b.clone() }) + (Precision::Exact(a), Precision::Exact(b)) => { + Precision::Exact(if a >= b { a.clone() } else { b.clone() }) } - (Sharpness::Inexact(a), Sharpness::Exact(b)) - | (Sharpness::Exact(a), Sharpness::Inexact(b)) - | (Sharpness::Inexact(a), Sharpness::Inexact(b)) => { - Sharpness::Inexact(if a >= b { a.clone() } else { b.clone() }) + (Precision::Inexact(a), Precision::Exact(b)) + | (Precision::Exact(a), Precision::Inexact(b)) + | (Precision::Inexact(a), Precision::Inexact(b)) => { + Precision::Inexact(if a >= b { a.clone() } else { b.clone() }) } - (_, _) => Sharpness::Absent, + (_, _) => Precision::Absent, } } /// Returns the minimum of two (possibly inexact) values, conservatively /// propagating exactness information. If one of the input values is - /// [`Sharpness::Absent`], the result is `Absent` too. - pub fn min(&self, other: &Sharpness) -> Sharpness { + /// [`Precision::Absent`], the result is `Absent` too. + pub fn min(&self, other: &Precision) -> Precision { match (self, other) { - (Sharpness::Exact(a), Sharpness::Exact(b)) => { - Sharpness::Exact(if a >= b { b.clone() } else { a.clone() }) + (Precision::Exact(a), Precision::Exact(b)) => { + Precision::Exact(if a >= b { b.clone() } else { a.clone() }) } - (Sharpness::Inexact(a), Sharpness::Exact(b)) - | (Sharpness::Exact(a), Sharpness::Inexact(b)) - | (Sharpness::Inexact(a), Sharpness::Inexact(b)) => { - Sharpness::Inexact(if a >= b { b.clone() } else { a.clone() }) + (Precision::Inexact(a), Precision::Exact(b)) + | (Precision::Exact(a), Precision::Inexact(b)) + | (Precision::Inexact(a), Precision::Inexact(b)) => { + Precision::Inexact(if a >= b { b.clone() } else { a.clone() }) } - (_, _) => Sharpness::Absent, + (_, _) => Precision::Absent, } } - /// Demotes the sharpness state to inexact (if present). + /// Demotes the precision state from exact to inexact (if present). pub fn to_inexact(self) -> Self { match self { - Sharpness::Exact(value) => Sharpness::Inexact(value), + Precision::Exact(value) => Precision::Inexact(value), _ => self, } } } -impl Sharpness { +impl Precision { /// Calculates the sum of two (possibly inexact) [`usize`] values, /// conservatively propagating exactness information. If one of the input - /// values is [`Sharpness::Absent`], the result is `Absent` too. - pub fn add(&self, other: &Sharpness) -> Sharpness { + /// values is [`Precision::Absent`], the result is `Absent` too. + pub fn add(&self, other: &Precision) -> Precision { match (self, other) { - (Sharpness::Exact(a), Sharpness::Exact(b)) => Sharpness::Exact(a + b), - (Sharpness::Inexact(a), Sharpness::Exact(b)) - | (Sharpness::Exact(a), Sharpness::Inexact(b)) - | (Sharpness::Inexact(a), Sharpness::Inexact(b)) => Sharpness::Inexact(a + b), - (_, _) => Sharpness::Absent, + (Precision::Exact(a), Precision::Exact(b)) => Precision::Exact(a + b), + (Precision::Inexact(a), Precision::Exact(b)) + | (Precision::Exact(a), Precision::Inexact(b)) + | (Precision::Inexact(a), Precision::Inexact(b)) => Precision::Inexact(a + b), + (_, _) => Precision::Absent, } } /// Calculates the difference of two (possibly inexact) [`usize`] values, /// conservatively propagating exactness information. If one of the input - /// values is [`Sharpness::Absent`], the result is `Absent` too. - pub fn sub(&self, other: &Sharpness) -> Sharpness { + /// values is [`Precision::Absent`], the result is `Absent` too. + pub fn sub(&self, other: &Precision) -> Precision { match (self, other) { - (Sharpness::Exact(a), Sharpness::Exact(b)) => Sharpness::Exact(a - b), - (Sharpness::Inexact(a), Sharpness::Exact(b)) - | (Sharpness::Exact(a), Sharpness::Inexact(b)) - | (Sharpness::Inexact(a), Sharpness::Inexact(b)) => Sharpness::Inexact(a - b), - (_, _) => Sharpness::Absent, + (Precision::Exact(a), Precision::Exact(b)) => Precision::Exact(a - b), + (Precision::Inexact(a), Precision::Exact(b)) + | (Precision::Exact(a), Precision::Inexact(b)) + | (Precision::Inexact(a), Precision::Inexact(b)) => Precision::Inexact(a - b), + (_, _) => Precision::Absent, } } /// Calculates the multiplication of two (possibly inexact) [`usize`] values, /// conservatively propagating exactness information. If one of the input - /// values is [`Sharpness::Absent`], the result is `Absent` too. - pub fn multiply(&self, other: &Sharpness) -> Sharpness { + /// values is [`Precision::Absent`], the result is `Absent` too. + pub fn multiply(&self, other: &Precision) -> Precision { match (self, other) { - (Sharpness::Exact(a), Sharpness::Exact(b)) => Sharpness::Exact(a * b), - (Sharpness::Inexact(a), Sharpness::Exact(b)) - | (Sharpness::Exact(a), Sharpness::Inexact(b)) - | (Sharpness::Inexact(a), Sharpness::Inexact(b)) => Sharpness::Inexact(a * b), - (_, _) => Sharpness::Absent, + (Precision::Exact(a), Precision::Exact(b)) => Precision::Exact(a * b), + (Precision::Inexact(a), Precision::Exact(b)) + | (Precision::Exact(a), Precision::Inexact(b)) + | (Precision::Inexact(a), Precision::Inexact(b)) => Precision::Inexact(a * b), + (_, _) => Precision::Absent, } } } -impl Sharpness { +impl Precision { /// Calculates the sum of two (possibly inexact) [`ScalarValue`] values, /// conservatively propagating exactness information. If one of the input - /// values is [`Sharpness::Absent`], the result is `Absent` too. - pub fn add(&self, other: &Sharpness) -> Sharpness { + /// values is [`Precision::Absent`], the result is `Absent` too. + pub fn add(&self, other: &Precision) -> Precision { match (self, other) { - (Sharpness::Exact(a), Sharpness::Exact(b)) => { + (Precision::Exact(a), Precision::Exact(b)) => { if let Ok(result) = a.add(b) { - Sharpness::Exact(result) + Precision::Exact(result) } else { - Sharpness::Absent + Precision::Absent } } - (Sharpness::Inexact(a), Sharpness::Exact(b)) - | (Sharpness::Exact(a), Sharpness::Inexact(b)) - | (Sharpness::Inexact(a), Sharpness::Inexact(b)) => { + (Precision::Inexact(a), Precision::Exact(b)) + | (Precision::Exact(a), Precision::Inexact(b)) + | (Precision::Inexact(a), Precision::Inexact(b)) => { if let Ok(result) = a.add(b) { - Sharpness::Inexact(result) + Precision::Inexact(result) } else { - Sharpness::Absent + Precision::Absent } } - (_, _) => Sharpness::Absent, + (_, _) => Precision::Absent, } } } -impl Debug for Sharpness { +impl Debug for Precision { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Sharpness::Exact(inner) => write!(f, "Exact({:?})", inner), - Sharpness::Inexact(inner) => write!(f, "Inexact({:?})", inner), - Sharpness::Absent => write!(f, "Absent"), + Precision::Exact(inner) => write!(f, "Exact({:?})", inner), + Precision::Inexact(inner) => write!(f, "Inexact({:?})", inner), + Precision::Absent => write!(f, "Absent"), } } } -impl Display for Sharpness { +impl Display for Precision { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Sharpness::Exact(inner) => write!(f, "Exact({:?})", inner), - Sharpness::Inexact(inner) => write!(f, "Inexact({:?})", inner), - Sharpness::Absent => write!(f, "Absent"), + Precision::Exact(inner) => write!(f, "Exact({:?})", inner), + Precision::Inexact(inner) => write!(f, "Inexact({:?})", inner), + Precision::Absent => write!(f, "Absent"), } } } @@ -274,111 +277,111 @@ mod tests { #[test] fn test_get_value() { - let exact_sharpness = Sharpness::Exact(42); - let inexact_sharpness = Sharpness::Inexact(23); - let absent_sharpness = Sharpness::::Absent; + let exact_precision = Precision::Exact(42); + let inexact_precision = Precision::Inexact(23); + let absent_precision = Precision::::Absent; - assert_eq!(*exact_sharpness.get_value().unwrap(), 42); - assert_eq!(*inexact_sharpness.get_value().unwrap(), 23); - assert_eq!(absent_sharpness.get_value(), None); + assert_eq!(*exact_precision.get_value().unwrap(), 42); + assert_eq!(*inexact_precision.get_value().unwrap(), 23); + assert_eq!(absent_precision.get_value(), None); } #[test] fn test_map() { - let exact_sharpness = Sharpness::Exact(42); - let inexact_sharpness = Sharpness::Inexact(23); - let absent_sharpness = Sharpness::Absent; + let exact_precision = Precision::Exact(42); + let inexact_precision = Precision::Inexact(23); + let absent_precision = Precision::Absent; let squared = |x| x * x; - assert_eq!(exact_sharpness.map(squared), Sharpness::Exact(1764)); - assert_eq!(inexact_sharpness.map(squared), Sharpness::Inexact(529)); - assert_eq!(absent_sharpness.map(squared), Sharpness::Absent); + assert_eq!(exact_precision.map(squared), Precision::Exact(1764)); + assert_eq!(inexact_precision.map(squared), Precision::Inexact(529)); + assert_eq!(absent_precision.map(squared), Precision::Absent); } #[test] fn test_is_exact() { - let exact_sharpness = Sharpness::Exact(42); - let inexact_sharpness = Sharpness::Inexact(23); - let absent_sharpness = Sharpness::::Absent; + let exact_precision = Precision::Exact(42); + let inexact_precision = Precision::Inexact(23); + let absent_precision = Precision::::Absent; - assert_eq!(exact_sharpness.is_exact(), Some(true)); - assert_eq!(inexact_sharpness.is_exact(), Some(false)); - assert_eq!(absent_sharpness.is_exact(), None); + assert_eq!(exact_precision.is_exact(), Some(true)); + assert_eq!(inexact_precision.is_exact(), Some(false)); + assert_eq!(absent_precision.is_exact(), None); } #[test] fn test_max() { - let sharpness1 = Sharpness::Exact(42); - let sharpness2 = Sharpness::Inexact(23); - let sharpness3 = Sharpness::Exact(30); - let absent_sharpness = Sharpness::Absent; - - assert_eq!(sharpness1.max(&sharpness2), Sharpness::Inexact(42)); - assert_eq!(sharpness1.max(&sharpness3), Sharpness::Exact(42)); - assert_eq!(sharpness2.max(&sharpness3), Sharpness::Inexact(30)); - assert_eq!(sharpness1.max(&absent_sharpness), Sharpness::Absent); + let precision1 = Precision::Exact(42); + let precision2 = Precision::Inexact(23); + let precision3 = Precision::Exact(30); + let absent_precision = Precision::Absent; + + assert_eq!(precision1.max(&precision2), Precision::Inexact(42)); + assert_eq!(precision1.max(&precision3), Precision::Exact(42)); + assert_eq!(precision2.max(&precision3), Precision::Inexact(30)); + assert_eq!(precision1.max(&absent_precision), Precision::Absent); } #[test] fn test_min() { - let sharpness1 = Sharpness::Exact(42); - let sharpness2 = Sharpness::Inexact(23); - let sharpness3 = Sharpness::Exact(30); - let absent_sharpness = Sharpness::Absent; - - assert_eq!(sharpness1.min(&sharpness2), Sharpness::Inexact(23)); - assert_eq!(sharpness1.min(&sharpness3), Sharpness::Exact(30)); - assert_eq!(sharpness2.min(&sharpness3), Sharpness::Inexact(23)); - assert_eq!(sharpness1.min(&absent_sharpness), Sharpness::Absent); + let precision1 = Precision::Exact(42); + let precision2 = Precision::Inexact(23); + let precision3 = Precision::Exact(30); + let absent_precision = Precision::Absent; + + assert_eq!(precision1.min(&precision2), Precision::Inexact(23)); + assert_eq!(precision1.min(&precision3), Precision::Exact(30)); + assert_eq!(precision2.min(&precision3), Precision::Inexact(23)); + assert_eq!(precision1.min(&absent_precision), Precision::Absent); } #[test] fn test_to_inexact() { - let exact_sharpness = Sharpness::Exact(42); - let inexact_sharpness = Sharpness::Inexact(42); - let absent_sharpness = Sharpness::::Absent; + let exact_precision = Precision::Exact(42); + let inexact_precision = Precision::Inexact(42); + let absent_precision = Precision::::Absent; - assert_eq!(exact_sharpness.clone().to_inexact(), inexact_sharpness); - assert_eq!(inexact_sharpness.clone().to_inexact(), inexact_sharpness); - assert_eq!(absent_sharpness.clone().to_inexact(), absent_sharpness); + assert_eq!(exact_precision.clone().to_inexact(), inexact_precision); + assert_eq!(inexact_precision.clone().to_inexact(), inexact_precision); + assert_eq!(absent_precision.clone().to_inexact(), absent_precision); } #[test] fn test_add() { - let sharpness1 = Sharpness::Exact(42); - let sharpness2 = Sharpness::Inexact(23); - let sharpness3 = Sharpness::Exact(30); - let absent_sharpness = Sharpness::Absent; - - assert_eq!(sharpness1.add(&sharpness2), Sharpness::Inexact(65)); - assert_eq!(sharpness1.add(&sharpness3), Sharpness::Exact(72)); - assert_eq!(sharpness2.add(&sharpness3), Sharpness::Inexact(53)); - assert_eq!(sharpness1.add(&absent_sharpness), Sharpness::Absent); + let precision1 = Precision::Exact(42); + let precision2 = Precision::Inexact(23); + let precision3 = Precision::Exact(30); + let absent_precision = Precision::Absent; + + assert_eq!(precision1.add(&precision2), Precision::Inexact(65)); + assert_eq!(precision1.add(&precision3), Precision::Exact(72)); + assert_eq!(precision2.add(&precision3), Precision::Inexact(53)); + assert_eq!(precision1.add(&absent_precision), Precision::Absent); } #[test] fn test_sub() { - let sharpness1 = Sharpness::Exact(42); - let sharpness2 = Sharpness::Inexact(23); - let sharpness3 = Sharpness::Exact(30); - let absent_sharpness = Sharpness::Absent; - - assert_eq!(sharpness1.sub(&sharpness2), Sharpness::Inexact(19)); - assert_eq!(sharpness1.sub(&sharpness3), Sharpness::Exact(12)); - assert_eq!(sharpness1.sub(&absent_sharpness), Sharpness::Absent); + let precision1 = Precision::Exact(42); + let precision2 = Precision::Inexact(23); + let precision3 = Precision::Exact(30); + let absent_precision = Precision::Absent; + + assert_eq!(precision1.sub(&precision2), Precision::Inexact(19)); + assert_eq!(precision1.sub(&precision3), Precision::Exact(12)); + assert_eq!(precision1.sub(&absent_precision), Precision::Absent); } #[test] fn test_multiply() { - let sharpness1 = Sharpness::Exact(6); - let sharpness2 = Sharpness::Inexact(3); - let sharpness3 = Sharpness::Exact(5); - let absent_sharpness = Sharpness::Absent; - - assert_eq!(sharpness1.multiply(&sharpness2), Sharpness::Inexact(18)); - assert_eq!(sharpness1.multiply(&sharpness3), Sharpness::Exact(30)); - assert_eq!(sharpness2.multiply(&sharpness3), Sharpness::Inexact(15)); - assert_eq!(sharpness1.multiply(&absent_sharpness), Sharpness::Absent); + let precision1 = Precision::Exact(6); + let precision2 = Precision::Inexact(3); + let precision3 = Precision::Exact(5); + let absent_precision = Precision::Absent; + + assert_eq!(precision1.multiply(&precision2), Precision::Inexact(18)); + assert_eq!(precision1.multiply(&precision3), Precision::Exact(30)); + assert_eq!(precision2.multiply(&precision3), Precision::Inexact(15)); + assert_eq!(precision1.multiply(&absent_precision), Precision::Absent); } }