This is an automated email from the ASF dual-hosted git repository.

akurmustafa pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new 8ae36b7511 [minor]: Update median implementation (#13554)
8ae36b7511 is described below

commit 8ae36b75116b62ec7c38abb1753bce86e25f4299
Author: Mustafa Akur <[email protected]>
AuthorDate: Fri Nov 29 15:15:13 2024 -0800

    [minor]: Update median implementation (#13554)
    
    * Initial commit
    
    * Minor changes
    
    * Update implementation to remove Option
    
    * Use max_by api
    
    * Fix error
    
    * Update datafusion/functions-aggregate/src/median.rs
    
    ---------
    
    Co-authored-by: Oleks V <[email protected]>
---
 datafusion/functions-aggregate/src/median.rs | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/datafusion/functions-aggregate/src/median.rs 
b/datafusion/functions-aggregate/src/median.rs
index 5b87922985..bcffb19b75 100644
--- a/datafusion/functions-aggregate/src/median.rs
+++ b/datafusion/functions-aggregate/src/median.rs
@@ -15,6 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use std::cmp::Ordering;
 use std::fmt::{Debug, Formatter};
 use std::mem::{size_of, size_of_val};
 use std::sync::{Arc, OnceLock};
@@ -30,7 +31,7 @@ use arrow::{
 
 use arrow::array::Array;
 use arrow::array::ArrowNativeTypeOp;
-use arrow::datatypes::ArrowNativeType;
+use arrow::datatypes::{ArrowNativeType, ArrowPrimitiveType};
 
 use datafusion_common::{DataFusionError, HashSet, Result, ScalarValue};
 use datafusion_expr::aggregate_doc_sections::DOC_SECTION_GENERAL;
@@ -310,6 +311,21 @@ impl<T: ArrowNumericType> Accumulator for 
DistinctMedianAccumulator<T> {
     }
 }
 
+/// Get maximum entry in the slice,
+fn slice_max<T>(array: &[T::Native]) -> T::Native
+where
+    T: ArrowPrimitiveType,
+    T::Native: PartialOrd, // Ensure the type supports PartialOrd for 
comparison
+{
+    // Make sure that, array is not empty.
+    debug_assert!(!array.is_empty());
+    // `.unwrap()` is safe here as the array is supposed to be non-empty
+    *array
+        .iter()
+        .max_by(|x, y| x.partial_cmp(y).unwrap_or(Ordering::Less))
+        .unwrap()
+}
+
 fn calculate_median<T: ArrowNumericType>(
     mut values: Vec<T::Native>,
 ) -> Option<T::Native> {
@@ -320,8 +336,11 @@ fn calculate_median<T: ArrowNumericType>(
         None
     } else if len % 2 == 0 {
         let (low, high, _) = values.select_nth_unstable_by(len / 2, cmp);
-        let (_, low, _) = low.select_nth_unstable_by(low.len() - 1, cmp);
-        let median = 
low.add_wrapping(*high).div_wrapping(T::Native::usize_as(2));
+        // Get the maximum of the low (left side after bi-partitioning)
+        let left_max = slice_max::<T>(low);
+        let median = left_max
+            .add_wrapping(*high)
+            .div_wrapping(T::Native::usize_as(2));
         Some(median)
     } else {
         let (_, median, _) = values.select_nth_unstable_by(len / 2, cmp);


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

Reply via email to