andygrove commented on code in PR #4941:
URL: https://github.com/apache/datafusion-comet/pull/4941#discussion_r3603739076


##########
native/spark-expr/src/conversion_funcs/numeric.rs:
##########
@@ -1160,6 +1104,111 @@ mod tests {
         assert_eq!(decimal_array.value(1), -10000); // -100 * 10^2
         assert!(decimal_array.is_null(2));
     }
+

Review Comment:
   Extended `test_cast_float64_to_int8_legacy_wraps` with `3e9`, 
`f64::INFINITY`, and `f64::NEG_INFINITY`. `3e9`/`+inf` saturate to `i32::MAX` 
(0x7FFFFFFF) and narrow to `-1` as i8; `-inf` saturates to `i32::MIN` 
(0x80000000) and narrows to `0` as i8. Those asserts pin the 
saturate-then-narrow chain end to end.



##########
native/spark-expr/src/conversion_funcs/numeric.rs:
##########
@@ -301,52 +301,37 @@ macro_rules! cast_float_to_int16_down {
         $rust_dest_type:ty,
         $src_type_str:expr,
         $dest_type_str:expr,
+        $dest_arrow_type:ty,
         $format_str:expr
     ) => {{
         let cast_array = $array
             .as_any()
             .downcast_ref::<$src_array_type>()
             .expect(concat!("Expected a ", stringify!($src_array_type)));
 
-        let output_array = match $eval_mode {
-            EvalMode::Ansi => cast_array
-                .iter()
-                .map(|value| match value {
-                    Some(value) => {
-                        let is_overflow = value.is_nan() || value.abs() as i32 
== i32::MAX;
-                        if is_overflow {
-                            return Err(cast_overflow(
-                                &format!($format_str, value).replace("e", "E"),
-                                $src_type_str,
-                                $dest_type_str,
-                            ));
-                        }
-                        let i32_value = value as i32;
-                        <$rust_dest_type>::try_from(i32_value)
-                            .map_err(|_| {
-                                cast_overflow(
-                                    &format!($format_str, value).replace("e", 
"E"),
-                                    $src_type_str,
-                                    $dest_type_str,
-                                )
-                            })
-                            .map(Some)
-                    }
-                    None => Ok(None),
-                })
-                .collect::<Result<$dest_array_type, _>>()?,
-            _ => cast_array
-                .iter()
-                .map(|value| match value {
-                    Some(value) => {
-                        let i32_value = value as i32;
-                        Ok::<Option<$rust_dest_type>, SparkError>(Some(
-                            i32_value as $rust_dest_type,
-                        ))
-                    }
-                    None => Ok(None),
+        // Spark casts float -> Byte/Short by going through Int first (with 
its own overflow),
+        // then narrowing. `unary`/`try_unary` map the values buffer in one 
pass and carry the
+        // null buffer over, replacing the per-element iterator-collect.
+        let output_array: $dest_array_type = match $eval_mode {
+            EvalMode::Ansi => cast_array.try_unary::<_, $dest_arrow_type, 
SparkError>(|value| {
+                let is_overflow = value.is_nan() || value.abs() as i32 == 
i32::MAX;
+                if is_overflow {
+                    return Err(cast_overflow(
+                        &format!($format_str, value).replace("e", "E"),
+                        $src_type_str,
+                        $dest_type_str,
+                    ));
+                }
+                let i32_value = value as i32;
+                <$rust_dest_type>::try_from(i32_value).map_err(|_| {
+                    cast_overflow(
+                        &format!($format_str, value).replace("e", "E"),
+                        $src_type_str,
+                        $dest_type_str,
+                    )
                 })
-                .collect::<Result<$dest_array_type, _>>()?,
+            })?,
+            _ => cast_array.unary::<_, $dest_arrow_type>(|value| (value as 
i32) as $rust_dest_type),

Review Comment:
   Added a one-line comment on each of the four legacy `unary` arms (`:334`, 
`:373`, `:428`, `:473`) noting that `unary` runs the op on null slots too and 
stating why the as-cast or positive-divisor division is infallible for any bit 
pattern.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to