@@ -281,11 +281,22 @@ impl ScalarUDFImpl for FloorFunc {
281281
282282/// Compute preimage bounds for floor function on floating-point types.
283283/// For floor(x) = n, the preimage is [n, n+1).
284- /// Returns None if the value is non-finite or would lose precision.
284+ /// Returns None if:
285+ /// - The value is non-finite (infinity, NaN)
286+ /// - The value is not an integer (floor always returns integers, so floor(x) = 1.3 has no solution)
287+ /// - Adding 1 would lose precision at extreme values
285288fn float_preimage_bounds < F : Float > ( n : F ) -> Option < ( F , F ) > {
286289 let one = F :: one ( ) ;
287- // Check for non-finite values (infinity, NaN) or precision loss at extreme values
288- if !n. is_finite ( ) || n + one <= n {
290+ // Check for non-finite values (infinity, NaN)
291+ if !n. is_finite ( ) {
292+ return None ;
293+ }
294+ // floor always returns an integer, so if n has a fractional part, there's no solution
295+ if n. fract ( ) != F :: zero ( ) {
296+ return None ;
297+ }
298+ // Check for precision loss at extreme values
299+ if n + one <= n {
289300 return None ;
290301 }
291302 Some ( ( n, n + one) )
@@ -383,6 +394,15 @@ mod tests {
383394 ) ;
384395 }
385396
397+ #[ test]
398+ fn test_floor_preimage_non_integer_float ( ) {
399+ // floor(x) = 1.3 has NO SOLUTION because floor always returns an integer
400+ // Therefore preimage should return None for non-integer literals
401+ assert_preimage_none ( ScalarValue :: Float64 ( Some ( 1.3 ) ) ) ;
402+ assert_preimage_none ( ScalarValue :: Float64 ( Some ( -2.5 ) ) ) ;
403+ assert_preimage_none ( ScalarValue :: Float32 ( Some ( 3.14 ) ) ) ;
404+ }
405+
386406 #[ test]
387407 fn test_floor_preimage_integer_overflow ( ) {
388408 // All integer types at MAX value should return None
0 commit comments