@@ -315,6 +315,31 @@ impl Default for ListViewData {
315315 }
316316}
317317
318+ /// Walks parallel `(offset, size)` slices and marks every referenced position in `buf`.
319+ ///
320+ /// **Precondition**
321+ ///
322+ /// `offsets` and `sizes` must be the same length (which is always the case in valid `ListViewArray`s).
323+ fn fill_referenced_mask < O : IntegerPType , S : IntegerPType > (
324+ buf : & mut BitBufferMut ,
325+ offsets : & [ O ] ,
326+ sizes : & [ S ] ,
327+ ) {
328+ let len = offsets. len ( ) ;
329+
330+ assert_eq ! (
331+ len,
332+ sizes. len( ) ,
333+ "offsets and sizes must be the same length"
334+ ) ;
335+
336+ for i in 0 ..len {
337+ let start: usize = offsets[ i] . as_ ( ) ;
338+ let size: usize = sizes[ i] . as_ ( ) ;
339+ buf. fill_range ( start, start + size, true ) ;
340+ }
341+ }
342+
318343pub trait ListViewArrayExt : TypedArrayRef < ListView > {
319344 fn nullability ( & self ) -> crate :: dtype:: Nullability {
320345 match self . as_ref ( ) . dtype ( ) {
@@ -402,35 +427,31 @@ pub trait ListViewArrayExt: TypedArrayRef<ListView> {
402427 }
403428
404429 /// Returns a [`Mask`] of length `elements.len()` where each bit is set iff that
405- /// position in `elements` is referenced by at least one view.
430+ /// position in `elements` is referenced by at least one view. Caller must ensure `elements`
431+ /// is non-empty.
406432 ///
407433 /// Walks every `(offset, size)` pair, canonicalizes both `offsets` and `sizes`,
408434 /// and allocates a `BitBuffer` of length `elements.len()`, so it is extremely costly.
409435 ///
410436 /// **Preconditions**
411437 ///
412- /// Assumes that `self.elements()` is non-empty.
413- #[ allow( clippy:: cognitive_complexity) ]
438+ /// `self.elements()` must be non-empty.
414439 fn compute_referenced_elements_mask ( & self , ctx : & mut ExecutionCtx ) -> VortexResult < Mask > {
415- debug_assert ! ( !self . elements( ) . is_empty( ) ) ;
440+ assert ! ( !self . elements( ) . is_empty( ) ) ;
416441 let len = self . elements ( ) . len ( ) ;
417442
418443 let offsets_primitive = self . offsets ( ) . clone ( ) . execute :: < PrimitiveArray > ( ctx) ?;
419444 let sizes_primitive = self . sizes ( ) . clone ( ) . execute :: < PrimitiveArray > ( ctx) ?;
420445
421446 let mut buf = BitBufferMut :: new_unset ( len) ;
422- let offset_len = self . as_ref ( ) . len ( ) ;
423447
424448 match_each_integer_ptype ! ( offsets_primitive. ptype( ) , |O | {
425449 match_each_integer_ptype!( sizes_primitive. ptype( ) , |S | {
426- let offsets_slice = offsets_primitive. as_slice:: <O >( ) ;
427- let sizes_slice = sizes_primitive. as_slice:: <S >( ) ;
428-
429- for i in 0 ..offset_len {
430- let start: usize = offsets_slice[ i] . as_( ) ;
431- let size: usize = sizes_slice[ i] . as_( ) ;
432- buf. fill_range( start, start + size, true ) ;
433- }
450+ fill_referenced_mask:: <O , S >(
451+ & mut buf,
452+ offsets_primitive. as_slice:: <O >( ) ,
453+ sizes_primitive. as_slice:: <S >( ) ,
454+ ) ;
434455 } )
435456 } ) ;
436457
@@ -464,7 +485,7 @@ pub trait ListViewArrayExt: TypedArrayRef<ListView> {
464485 /// Exact for non-overlapping views, but overcounts when multiple views share the same elements.
465486 ///
466487 /// Returns `Ok(1.0)` when `elements` is empty.
467- fn estimate_density ( & self , ctx : & mut ExecutionCtx ) -> VortexResult < f32 > {
488+ fn upper_bound_density ( & self , ctx : & mut ExecutionCtx ) -> VortexResult < f32 > {
468489 let n_elts = self . elements ( ) . len ( ) ;
469490 if n_elts == 0 {
470491 return Ok ( 1.0 ) ;
@@ -479,10 +500,10 @@ pub trait ListViewArrayExt: TypedArrayRef<ListView> {
479500 let sizes_sum = sizes
480501 . statistics ( )
481502 . compute_stat ( Stat :: Sum , ctx) ?
482- . ok_or_else ( || vortex_err ! ( "Sum stat unavailable for sizes" ) ) ?
503+ . vortex_expect ( "sizes array has integer ptype elements" )
483504 . as_primitive ( )
484505 . as_ :: < u64 > ( )
485- . ok_or_else ( || vortex_err ! ( "could not cast sum of sizes to u64") ) ? ;
506+ . vortex_expect ( "integer ptypes can be upcast to u64") ;
486507
487508 // if the same elements are referenced more than once the estimate may be
488509 // greater than 1.0, so clamp
0 commit comments