Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions datafusion/common/src/rounding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub trait FloatBits {

/// The integer value 0, used in bitwise operations.
const ZERO: Self::Item;
const NEG_ZERO: Self::Item;

/// Converts the floating-point value to its bitwise representation.
fn to_bits(self) -> Self::Item;
Expand All @@ -101,6 +102,7 @@ impl FloatBits for f32 {
const CLEAR_SIGN_MASK: u32 = 0x7fff_ffff;
const ONE: Self::Item = 1;
const ZERO: Self::Item = 0;
const NEG_ZERO: Self::Item = 0x8000_0000;

fn to_bits(self) -> Self::Item {
self.to_bits()
Expand Down Expand Up @@ -130,6 +132,7 @@ impl FloatBits for f64 {
const CLEAR_SIGN_MASK: u64 = 0x7fff_ffff_ffff_ffff;
const ONE: Self::Item = 1;
const ZERO: Self::Item = 0;
const NEG_ZERO: Self::Item = 0x8000_0000_0000_0000;

fn to_bits(self) -> Self::Item {
self.to_bits()
Expand Down Expand Up @@ -175,8 +178,10 @@ pub fn next_up<F: FloatBits + Copy>(float: F) -> F {
}

let abs = bits & F::CLEAR_SIGN_MASK;
let next_bits = if abs == F::ZERO {
let next_bits = if bits == F::ZERO {
F::TINY_BITS
} else if abs == F::ZERO {
F::ZERO
} else if bits == abs {
bits + F::ONE
} else {
Expand Down Expand Up @@ -206,8 +211,11 @@ pub fn next_down<F: FloatBits + Copy>(float: F) -> F {
if float.float_is_nan() || bits == F::neg_infinity().to_bits() {
return float;
}

let abs = bits & F::CLEAR_SIGN_MASK;
let next_bits = if abs == F::ZERO {
let next_bits = if bits == F::ZERO {
F::NEG_ZERO
} else if abs == F::ZERO {
F::NEG_TINY_BITS
} else if bits == abs {
bits - F::ONE
Expand Down Expand Up @@ -396,4 +404,32 @@ mod tests {
let result = next_down(value);
assert!(result.is_nan());
}

#[test]
fn test_next_up_neg_zero_f32() {
let value: f32 = -0.0;
let result = next_up(value);
assert_eq!(result, 0.0);
}

#[test]
fn test_next_down_zero_f32() {
let value: f32 = 0.0;
let result = next_down(value);
assert_eq!(result, -0.0);
}

#[test]
fn test_next_up_neg_zero_f64() {
let value: f64 = -0.0;
let result = next_up(value);
assert_eq!(result, 0.0);
}

#[test]
fn test_next_down_zero_f64() {
let value: f64 = 0.0;
let result = next_down(value);
assert_eq!(result, -0.0);
}
}
80 changes: 80 additions & 0 deletions datafusion/expr-common/src/interval_arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3698,6 +3698,76 @@ mod tests {
Interval::make(Some(-500.0_f64), Some(1000.0_f64))?,
Interval::make(Some(-500.0_f64), Some(500.0_f64))?,
),
(
Interval::make(Some(0_i64), Some(0_i64))?,
Interval::make(Some(-0_i64), Some(0_i64))?,
true,
Interval::make(Some(0_i64), Some(0_i64))?,
Interval::make(Some(-0_i64), Some(0_i64))?,
),
(
Interval::make(Some(-0_i64), Some(0_i64))?,
Interval::make(Some(-0_i64), Some(-0_i64))?,
true,
Interval::make(Some(-0_i64), Some(0_i64))?,
Interval::make(Some(-0_i64), Some(-0_i64))?,
),
(
Interval::make(Some(0.0_f64), Some(0.0_f64))?,
Interval::make(Some(-0.0_f64), Some(0.0_f64))?,
true,
Interval::make(Some(0.0_f64), Some(0.0_f64))?,
Interval::make(Some(-0.0_f64), Some(0.0_f64))?,
),
(
Interval::make(Some(0.0_f64), Some(0.0_f64))?,
Interval::make(Some(-0.0_f64), Some(0.0_f64))?,
false,
Interval::make(Some(0.0_f64), Some(0.0_f64))?,
Interval::make(Some(-0.0_f64), Some(-0.0_f64))?,
),
(
Interval::make(Some(-0.0_f64), Some(0.0_f64))?,
Interval::make(Some(-0.0_f64), Some(-0.0_f64))?,
true,
Interval::make(Some(-0.0_f64), Some(0.0_f64))?,
Interval::make(Some(-0.0_f64), Some(-0.0_f64))?,
),
(
Interval::make(Some(-0.0_f64), Some(0.0_f64))?,
Interval::make(Some(-0.0_f64), Some(-0.0_f64))?,
false,
Interval::make(Some(0.0_f64), Some(0.0_f64))?,
Interval::make(Some(-0.0_f64), Some(-0.0_f64))?,
),
(
Interval::make(Some(0_i64), None)?,
Interval::make(Some(-0_i64), None)?,
true,
Interval::make(Some(0_i64), None)?,
Interval::make(Some(-0_i64), None)?,
),
(
Interval::make(Some(0_i64), None)?,
Interval::make(Some(-0_i64), None)?,
false,
Interval::make(Some(1_i64), None)?,
Interval::make(Some(-0_i64), None)?,
),
(
Interval::make(Some(0.0_f64), None)?,
Interval::make(Some(-0.0_f64), None)?,
true,
Interval::make(Some(0.0_f64), None)?,
Interval::make(Some(-0.0_f64), None)?,
),
(
Interval::make(Some(0.0_f64), None)?,
Interval::make(Some(-0.0_f64), None)?,
false,
Interval::make(Some(0.0_f64), None)?,
Interval::make(Some(-0.0_f64), None)?,
),
];
for (first, second, includes_endpoints, left_modified, right_modified) in cases {
assert_eq!(
Expand All @@ -3717,6 +3787,16 @@ mod tests {
Interval::make(Some(1500.0_f32), Some(2000.0_f32))?,
false,
),
(
Interval::make(Some(0_i64), Some(0_i64))?,
Interval::make(Some(-0_i64), Some(0_i64))?,
false,
),
(
Interval::make(Some(-0_i64), Some(0_i64))?,
Interval::make(Some(-0_i64), Some(-0_i64))?,
false,
),
];
for (first, second, includes_endpoints) in infeasible_cases {
assert_eq!(satisfy_greater(&first, &second, !includes_endpoints)?, None);
Expand Down
Loading