20
20
*/
21
21
22
22
use std:: any:: Any ;
23
+ use std:: cmp:: Ordering ;
23
24
use std:: collections:: HashMap ;
24
25
use std:: fmt:: { Display , Formatter } ;
25
26
use std:: hash:: Hash ;
@@ -29,7 +30,7 @@ use std::str::FromStr;
29
30
pub use _serde:: RawLiteral ;
30
31
use chrono:: { DateTime , NaiveDate , NaiveDateTime , NaiveTime , TimeZone , Utc } ;
31
32
use num_bigint:: BigInt ;
32
- use ordered_float:: OrderedFloat ;
33
+ use ordered_float:: { Float , OrderedFloat } ;
33
34
use rust_decimal:: Decimal ;
34
35
use rust_decimal:: prelude:: ToPrimitive ;
35
36
use serde:: de:: {
@@ -214,6 +215,36 @@ impl<'de> Deserialize<'de> for Datum {
214
215
}
215
216
}
216
217
218
+ // Compare following iceberg float ordering rules:
219
+ // -NaN < -Infinity < -value < -0 < 0 < value < Infinity < NaN
220
+ fn iceberg_float_cmp < T : Float > ( a : T , b : T ) -> Option < Ordering > {
221
+ if a. is_nan ( ) && b. is_nan ( ) {
222
+ return match ( a. is_sign_negative ( ) , b. is_sign_negative ( ) ) {
223
+ ( true , false ) => Some ( Ordering :: Less ) ,
224
+ ( false , true ) => Some ( Ordering :: Greater ) ,
225
+ _ => Some ( Ordering :: Equal ) ,
226
+ } ;
227
+ }
228
+
229
+ if a. is_nan ( ) {
230
+ return Some ( if a. is_sign_negative ( ) {
231
+ Ordering :: Less
232
+ } else {
233
+ Ordering :: Greater
234
+ } ) ;
235
+ }
236
+
237
+ if b. is_nan ( ) {
238
+ return Some ( if b. is_sign_negative ( ) {
239
+ Ordering :: Greater
240
+ } else {
241
+ Ordering :: Less
242
+ } ) ;
243
+ }
244
+
245
+ a. partial_cmp ( & b)
246
+ }
247
+
217
248
impl PartialOrd for Datum {
218
249
fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
219
250
match ( & self . literal , & other. literal , & self . r#type , & other. r#type ) {
@@ -241,13 +272,13 @@ impl PartialOrd for Datum {
241
272
PrimitiveLiteral :: Float ( other_val) ,
242
273
PrimitiveType :: Float ,
243
274
PrimitiveType :: Float ,
244
- ) => val . partial_cmp ( other_val) ,
275
+ ) => iceberg_float_cmp ( * val , * other_val) ,
245
276
(
246
277
PrimitiveLiteral :: Double ( val) ,
247
278
PrimitiveLiteral :: Double ( other_val) ,
248
279
PrimitiveType :: Double ,
249
280
PrimitiveType :: Double ,
250
- ) => val . partial_cmp ( other_val) ,
281
+ ) => iceberg_float_cmp ( * val , * other_val) ,
251
282
(
252
283
PrimitiveLiteral :: Int ( val) ,
253
284
PrimitiveLiteral :: Int ( other_val) ,
@@ -3845,4 +3876,71 @@ mod tests {
3845
3876
3846
3877
assert_eq ! ( result, expected) ;
3847
3878
}
3879
+
3880
+ #[ test]
3881
+ fn test_iceberg_float_order ( ) {
3882
+ // Test float ordering
3883
+ let float_values = vec ! [
3884
+ Datum :: float( f32 :: NAN ) ,
3885
+ Datum :: float( -f32 :: NAN ) ,
3886
+ Datum :: float( f32 :: MAX ) ,
3887
+ Datum :: float( f32 :: MIN ) ,
3888
+ Datum :: float( f32 :: INFINITY ) ,
3889
+ Datum :: float( -f32 :: INFINITY ) ,
3890
+ Datum :: float( 1.0 ) ,
3891
+ Datum :: float( -1.0 ) ,
3892
+ Datum :: float( 0.0 ) ,
3893
+ Datum :: float( -0.0 ) ,
3894
+ ] ;
3895
+
3896
+ let mut float_sorted = float_values. clone ( ) ;
3897
+ float_sorted. sort_by ( |a, b| a. partial_cmp ( b) . unwrap ( ) ) ;
3898
+
3899
+ let float_expected = vec ! [
3900
+ Datum :: float( -f32 :: NAN ) ,
3901
+ Datum :: float( -f32 :: INFINITY ) ,
3902
+ Datum :: float( f32 :: MIN ) ,
3903
+ Datum :: float( -1.0 ) ,
3904
+ Datum :: float( -0.0 ) ,
3905
+ Datum :: float( 0.0 ) ,
3906
+ Datum :: float( 1.0 ) ,
3907
+ Datum :: float( f32 :: MAX ) ,
3908
+ Datum :: float( f32 :: INFINITY ) ,
3909
+ Datum :: float( f32 :: NAN ) ,
3910
+ ] ;
3911
+
3912
+ assert_eq ! ( float_sorted, float_expected) ;
3913
+
3914
+ // Test double ordering
3915
+ let double_values = vec ! [
3916
+ Datum :: double( f64 :: NAN ) ,
3917
+ Datum :: double( -f64 :: NAN ) ,
3918
+ Datum :: double( f64 :: INFINITY ) ,
3919
+ Datum :: double( -f64 :: INFINITY ) ,
3920
+ Datum :: double( f64 :: MAX ) ,
3921
+ Datum :: double( f64 :: MIN ) ,
3922
+ Datum :: double( 1.0 ) ,
3923
+ Datum :: double( -1.0 ) ,
3924
+ Datum :: double( 0.0 ) ,
3925
+ Datum :: double( -0.0 ) ,
3926
+ ] ;
3927
+
3928
+ let mut double_sorted = double_values. clone ( ) ;
3929
+ double_sorted. sort_by ( |a, b| a. partial_cmp ( b) . unwrap ( ) ) ;
3930
+
3931
+ let double_expected = vec ! [
3932
+ Datum :: double( -f64 :: NAN ) ,
3933
+ Datum :: double( -f64 :: INFINITY ) ,
3934
+ Datum :: double( f64 :: MIN ) ,
3935
+ Datum :: double( -1.0 ) ,
3936
+ Datum :: double( -0.0 ) ,
3937
+ Datum :: double( 0.0 ) ,
3938
+ Datum :: double( 1.0 ) ,
3939
+ Datum :: double( f64 :: MAX ) ,
3940
+ Datum :: double( f64 :: INFINITY ) ,
3941
+ Datum :: double( f64 :: NAN ) ,
3942
+ ] ;
3943
+
3944
+ assert_eq ! ( double_sorted, double_expected) ;
3945
+ }
3848
3946
}
0 commit comments