@@ -30,6 +30,7 @@ use crate::aggregate_fn::AggregateFnVTable;
3030use crate :: aggregate_fn:: DynAccumulator ;
3131use crate :: arrays:: Constant ;
3232use crate :: arrays:: Null ;
33+ use crate :: builtins:: ArrayBuiltins ;
3334use crate :: dtype:: DType ;
3435use crate :: dtype:: FieldNames ;
3536use crate :: dtype:: Nullability ;
@@ -200,10 +201,11 @@ pub struct IsSortedPartial {
200201 element_dtype : DType ,
201202}
202203
204+ static NAMES : std:: sync:: LazyLock < FieldNames > = std:: sync:: LazyLock :: new ( || {
205+ FieldNames :: from ( [ "is_sorted" , "strict" , "first_value" , "last_value" ] )
206+ } ) ;
207+
203208pub fn make_is_sorted_partial_dtype ( element_dtype : & DType ) -> DType {
204- static NAMES : std:: sync:: LazyLock < FieldNames > = std:: sync:: LazyLock :: new ( || {
205- FieldNames :: from ( [ "is_sorted" , "strict" , "first_value" , "last_value" ] )
206- } ) ;
207209 DType :: Struct (
208210 StructFields :: new (
209211 NAMES . clone ( ) ,
@@ -315,56 +317,48 @@ impl AggregateFnVTable for IsSorted {
315317 Ok ( ( ) )
316318 }
317319
318- fn flush ( & self , partial : & mut Self :: Partial ) -> VortexResult < Scalar > {
320+ fn to_scalar ( & self , partial : & Self :: Partial ) -> VortexResult < Scalar > {
319321 let dtype = make_is_sorted_partial_dtype ( & partial. element_dtype ) ;
320-
321- // Take ownership of the values to avoid cloning.
322- let first = partial. first_value . take ( ) ;
323- let last = partial. last_value . take ( ) ;
324- let is_sorted = partial. is_sorted ;
325- let strict = partial. strict ;
326-
327- // Reset state.
328- partial. is_sorted = true ;
329-
330- let result = match ( first, last) {
322+ Ok ( match ( & partial. first_value , & partial. last_value ) {
331323 ( None , _) => {
332324 // Empty accumulator — return null struct.
333325 Scalar :: null ( dtype)
334326 }
335327 ( Some ( first_value) , Some ( last_value) ) => {
336- // Values are already nullable from into_nullable_unchecked in accumulate.
337328 // SAFETY: We constructed partial_dtype and the children match its field dtypes.
338329 unsafe {
339330 Scalar :: struct_unchecked (
340331 dtype,
341332 [
342- Scalar :: bool ( is_sorted, Nullability :: NonNullable ) ,
343- Scalar :: bool ( strict, Nullability :: NonNullable ) ,
344- first_value,
345- last_value,
333+ Scalar :: bool ( partial . is_sorted , Nullability :: NonNullable ) ,
334+ Scalar :: bool ( partial . strict , Nullability :: NonNullable ) ,
335+ first_value. clone ( ) ,
336+ last_value. clone ( ) ,
346337 ] ,
347338 )
348339 }
349340 }
350341 ( Some ( first_value) , None ) => {
351- let cloned = first_value. clone ( ) ;
352342 // SAFETY: We constructed partial_dtype and the children match its field dtypes.
353343 unsafe {
354344 Scalar :: struct_unchecked (
355345 dtype,
356346 [
357- Scalar :: bool ( is_sorted, Nullability :: NonNullable ) ,
358- Scalar :: bool ( strict, Nullability :: NonNullable ) ,
359- first_value,
360- cloned ,
347+ Scalar :: bool ( partial . is_sorted , Nullability :: NonNullable ) ,
348+ Scalar :: bool ( partial . strict , Nullability :: NonNullable ) ,
349+ first_value. clone ( ) ,
350+ first_value . clone ( ) ,
361351 ] ,
362352 )
363353 }
364354 }
365- } ;
355+ } )
356+ }
366357
367- Ok ( result)
358+ fn reset ( & self , partial : & mut Self :: Partial ) {
359+ partial. is_sorted = true ;
360+ partial. first_value = None ;
361+ partial. last_value = None ;
368362 }
369363
370364 #[ inline]
@@ -479,21 +473,15 @@ impl AggregateFnVTable for IsSorted {
479473 }
480474
481475 fn finalize ( & self , partials : ArrayRef ) -> VortexResult < ArrayRef > {
482- // TODO: extract is_sorted field from struct array
483- Ok ( partials)
476+ partials. get_item ( NAMES . get ( 0 ) )
484477 }
485478
486- fn finalize_scalar ( & self , partial : Scalar ) -> VortexResult < Scalar > {
487- if partial. is_null ( ) {
479+ fn finalize_scalar ( & self , partial : & Self :: Partial ) -> VortexResult < Scalar > {
480+ if partial. first_value . is_none ( ) {
488481 // Empty accumulator → vacuously sorted.
489482 return Ok ( Scalar :: bool ( true , Nullability :: NonNullable ) ) ;
490483 }
491- let is_sorted_val = partial
492- . as_struct ( )
493- . field_by_idx ( 0 )
494- . map ( |s| s. as_bool ( ) . value ( ) . unwrap_or ( false ) )
495- . unwrap_or ( false ) ;
496- Ok ( Scalar :: bool ( is_sorted_val, Nullability :: NonNullable ) )
484+ Ok ( Scalar :: bool ( partial. is_sorted , Nullability :: NonNullable ) )
497485 }
498486}
499487
0 commit comments