Skip to content

Commit f65a8ff

Browse files
committed
wip
Signed-off-by: Joe Isaacs <[email protected]>
1 parent 6eb6988 commit f65a8ff

File tree

3 files changed

+210
-23
lines changed

3 files changed

+210
-23
lines changed

vortex-compute/src/arithmetic/pvector.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,15 +174,15 @@ mod tests {
174174
let right = PVector::new(buffer![10u32, 20, 30, 40], Mask::new_true(4));
175175

176176
let result = Arithmetic::<WrappingAdd, _>::eval(left, &right);
177-
let expected = PVector::new_valid(buffer![11u32, 22, 33, 44]);
177+
let expected = PVector::from(buffer![11u32, 22, 33, 44]);
178178
assert_eq!(result, expected);
179179
}
180180

181181
#[test]
182182
fn test_add_scalar() {
183183
let vec = PVector::new(buffer![1u32, 2, 3, 4], Mask::new_true(4));
184184
let result = Arithmetic::<WrappingAdd, _>::eval(vec, &10);
185-
let expected = PVector::new_valid(buffer![11u32, 12, 13, 14]);
185+
let expected = PVector::from(buffer![11u32, 12, 13, 14]);
186186
assert_eq!(result, expected);
187187
}
188188

@@ -203,15 +203,15 @@ mod tests {
203203
let right = PVector::new(buffer![1u32, 2, 3, 4], Mask::new_true(4));
204204

205205
let result = Arithmetic::<WrappingSub, _>::eval(left, &right);
206-
let expected = PVector::new_valid(buffer![9u32, 18, 27, 36]);
206+
let expected = PVector::from(buffer![9u32, 18, 27, 36]);
207207
assert_eq!(result, expected);
208208
}
209209

210210
#[test]
211211
fn test_sub_scalar() {
212212
let vec = PVector::new(buffer![10u32, 20, 30, 40], Mask::new_true(4));
213213
let result = Arithmetic::<WrappingSub, _>::eval(vec, &5);
214-
let expected = PVector::new_valid(buffer![5u32, 15, 25, 35]);
214+
let expected = PVector::from(buffer![5u32, 15, 25, 35]);
215215
assert_eq!(result, expected);
216216
}
217217

@@ -221,15 +221,15 @@ mod tests {
221221
let right = PVector::new(buffer![10u32, 20, 30, 40], Mask::new_true(4));
222222

223223
let result = Arithmetic::<WrappingMul, _>::eval(left, &right);
224-
let expected = PVector::new_valid(buffer![20u32, 60, 120, 200]);
224+
let expected = PVector::from(buffer![20u32, 60, 120, 200]);
225225
assert_eq!(result, expected);
226226
}
227227

228228
#[test]
229229
fn test_mul_scalar() {
230230
let vec = PVector::new(buffer![1u32, 2, 3, 4], Mask::new_true(4));
231231
let result = Arithmetic::<WrappingMul, _>::eval(vec, &10);
232-
let expected = PVector::new_valid(buffer![10u32, 20, 30, 40]);
232+
let expected = PVector::from(buffer![10u32, 20, 30, 40]);
233233
assert_eq!(result, expected);
234234
}
235235

vortex-vector/src/listview/vector.rs

Lines changed: 193 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use super::ListViewVectorMut;
1818
use crate::Vector;
1919
use crate::match_each_integer_pvector;
2020
use crate::match_each_integer_pvector_pair;
21+
use crate::primitive::PVector;
2122
use crate::primitive::PrimitiveVector;
2223
use crate::vector_ops::VectorMutOps;
2324
use crate::vector_ops::VectorOps;
@@ -110,10 +111,10 @@ fn listview_eq_impl<O, S>(
110111
validity: &Mask,
111112
self_elements: &Vector,
112113
other_elements: &Vector,
113-
self_offsets: &crate::primitive::PVector<O>,
114-
other_offsets: &crate::primitive::PVector<O>,
115-
self_sizes: &crate::primitive::PVector<S>,
116-
other_sizes: &crate::primitive::PVector<S>,
114+
self_offsets: &PVector<O>,
115+
other_offsets: &PVector<O>,
116+
self_sizes: &PVector<S>,
117+
other_sizes: &PVector<S>,
117118
) -> bool
118119
where
119120
O: vortex_dtype::NativePType + Copy,
@@ -459,3 +460,191 @@ fn validate_views_bound(
459460

460461
Ok(())
461462
}
463+
464+
#[cfg(test)]
465+
mod tests {
466+
use std::sync::Arc;
467+
468+
use vortex_buffer::Buffer;
469+
use vortex_mask::Mask;
470+
471+
use super::*;
472+
use crate::primitive::PVector;
473+
474+
/// Helper to create a ListViewVector with i32 elements and u32 offsets/sizes
475+
fn make_listview(
476+
elements: Vec<i32>,
477+
offsets: Vec<u32>,
478+
sizes: Vec<u32>,
479+
validity: Mask,
480+
) -> ListViewVector {
481+
let elem_validity = Mask::new_true(elements.len());
482+
let elements = PVector::new(Buffer::from(elements), elem_validity);
483+
let offsets_len = offsets.len();
484+
let sizes_len = sizes.len();
485+
let offsets = PVector::new(Buffer::from(offsets), Mask::new_true(offsets_len));
486+
let sizes = PVector::new(Buffer::from(sizes), Mask::new_true(sizes_len));
487+
ListViewVector::try_new(
488+
Arc::new(Vector::from(elements)),
489+
PrimitiveVector::from(offsets),
490+
PrimitiveVector::from(sizes),
491+
validity,
492+
)
493+
.unwrap()
494+
}
495+
496+
#[test]
497+
fn test_listview_eq_all_valid() {
498+
// All lists valid - direct element comparison
499+
let v1 = make_listview(
500+
vec![1, 2, 3, 4, 5],
501+
vec![0, 2, 3],
502+
vec![2, 1, 2],
503+
Mask::new_true(3),
504+
);
505+
let v2 = make_listview(
506+
vec![1, 2, 3, 4, 5],
507+
vec![0, 2, 3],
508+
vec![2, 1, 2],
509+
Mask::new_true(3),
510+
);
511+
assert_eq!(v1, v2);
512+
513+
// Different elements should not be equal
514+
let v3 = make_listview(
515+
vec![1, 2, 99, 4, 5],
516+
vec![0, 2, 3],
517+
vec![2, 1, 2],
518+
Mask::new_true(3),
519+
);
520+
assert_ne!(v1, v3);
521+
}
522+
523+
#[test]
524+
fn test_listview_eq_all_invalid() {
525+
// All lists invalid - elements don't matter
526+
let v1 = make_listview(
527+
vec![1, 2, 3, 4, 5],
528+
vec![0, 2, 3],
529+
vec![2, 1, 2],
530+
Mask::new_false(3),
531+
);
532+
let v2 = make_listview(
533+
vec![99, 99, 99, 99, 99],
534+
vec![0, 2, 3],
535+
vec![2, 1, 2],
536+
Mask::new_false(3),
537+
);
538+
assert_eq!(v1, v2);
539+
}
540+
541+
#[test]
542+
fn test_listview_eq_mixed_validity() {
543+
// Lists: [1,2], null, [4,5]
544+
// Elements at positions 2 (index of null list's elements) don't matter
545+
let validity = Mask::from_indices(3, vec![0, 2]);
546+
547+
let v1 = make_listview(
548+
vec![1, 2, 3, 4, 5],
549+
vec![0, 2, 3],
550+
vec![2, 1, 2],
551+
validity.clone(),
552+
);
553+
let v2 = make_listview(
554+
vec![1, 2, 3, 4, 5],
555+
vec![0, 2, 3],
556+
vec![2, 1, 2],
557+
validity.clone(),
558+
);
559+
assert_eq!(v1, v2);
560+
561+
// Element at position 2 is only used by the invalid list - should still be equal
562+
let v3 = make_listview(
563+
vec![1, 2, 99, 4, 5],
564+
vec![0, 2, 3],
565+
vec![2, 1, 2],
566+
validity.clone(),
567+
);
568+
assert_eq!(v1, v3, "Invalid list's elements should be ignored");
569+
570+
// Element at position 0 is used by valid list 0 - should NOT be equal
571+
let v4 = make_listview(
572+
vec![99, 2, 3, 4, 5],
573+
vec![0, 2, 3],
574+
vec![2, 1, 2],
575+
validity.clone(),
576+
);
577+
assert_ne!(v1, v4, "Valid list's elements must match");
578+
}
579+
580+
#[test]
581+
fn test_listview_eq_overlapping_slices() {
582+
// Overlapping ranges: list0=[0..3], list1=[1..4] (overlapping at positions 1,2)
583+
// This tests that the Vec<bool> approach handles overlaps correctly
584+
let v1 = make_listview(vec![1, 2, 3, 4], vec![0, 1], vec![3, 3], Mask::new_true(2));
585+
let v2 = make_listview(vec![1, 2, 3, 4], vec![0, 1], vec![3, 3], Mask::new_true(2));
586+
assert_eq!(v1, v2);
587+
588+
// Different element in overlapping region
589+
let v3 = make_listview(vec![1, 99, 3, 4], vec![0, 1], vec![3, 3], Mask::new_true(2));
590+
assert_ne!(v1, v3);
591+
}
592+
593+
#[test]
594+
fn test_listview_eq_overlapping_with_invalid() {
595+
// list0=[0..3] valid, list1=[1..4] invalid
596+
// Positions 1,2 are in overlap but list1 is invalid, so only list0's view matters
597+
let validity = Mask::from_indices(2, vec![0]); // only list 0 is valid
598+
599+
let v1 = make_listview(vec![1, 2, 3, 4], vec![0, 1], vec![3, 3], validity.clone());
600+
601+
// Element at position 3 is only used by invalid list1 - can differ
602+
let v2 = make_listview(vec![1, 2, 3, 99], vec![0, 1], vec![3, 3], validity.clone());
603+
assert_eq!(v1, v2, "Element used only by invalid list can differ");
604+
605+
// Element at position 2 is used by valid list0 - must match
606+
let v3 = make_listview(vec![1, 2, 99, 4], vec![0, 1], vec![3, 3], validity.clone());
607+
assert_ne!(v1, v3, "Element used by valid list must match");
608+
}
609+
610+
#[test]
611+
fn test_listview_eq_different_offsets_sizes() {
612+
// Same elements but different offsets at valid positions
613+
let v1 = make_listview(vec![1, 2, 3, 4], vec![0, 2], vec![2, 2], Mask::new_true(2));
614+
let v2 = make_listview(
615+
vec![1, 2, 3, 4],
616+
vec![0, 1], // different offset for list1
617+
vec![2, 2],
618+
Mask::new_true(2),
619+
);
620+
assert_ne!(v1, v2, "Different offsets at valid positions");
621+
622+
// Different sizes at valid positions
623+
let v3 = make_listview(
624+
vec![1, 2, 3, 4],
625+
vec![0, 2],
626+
vec![2, 1], // different size for list1
627+
Mask::new_true(2),
628+
);
629+
assert_ne!(v1, v3, "Different sizes at valid positions");
630+
}
631+
632+
#[test]
633+
fn test_listview_eq_different_validity() {
634+
let v1 = make_listview(vec![1, 2, 3, 4], vec![0, 2], vec![2, 2], Mask::new_true(2));
635+
let v2 = make_listview(
636+
vec![1, 2, 3, 4],
637+
vec![0, 2],
638+
vec![2, 2],
639+
Mask::from_indices(2, vec![0]), // only first list valid
640+
);
641+
assert_ne!(v1, v2, "Different validity patterns");
642+
}
643+
644+
#[test]
645+
fn test_listview_eq_empty() {
646+
let v1 = make_listview(vec![], vec![], vec![], Mask::new_true(0));
647+
let v2 = make_listview(vec![], vec![], vec![], Mask::new_true(0));
648+
assert_eq!(v1, v2);
649+
}
650+
}

vortex-vector/src/primitive/generic.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,6 @@ impl<T> PVector<T> {
6060
Self::try_new(elements, validity).vortex_expect("Failed to create `PVector`")
6161
}
6262

63-
/// Creates a new [`PVector<T>`] from the given elements buffer and validity mask.
64-
///
65-
/// # Panics
66-
///
67-
/// Panics if the length of the validity mask does not match the length of the elements buffer.
68-
pub fn new_valid(elements: Buffer<T>) -> Self {
69-
let len = elements.len();
70-
Self {
71-
elements,
72-
validity: Mask::new_true(len),
73-
}
74-
}
75-
7663
/// Tries to create a new [`PVector<T>`] from the given elements buffer and validity mask.
7764
///
7865
/// # Errors
@@ -237,3 +224,14 @@ impl<T: NativePType> VectorOps for PVector<T> {
237224
PVectorMut { elements, validity }
238225
}
239226
}
227+
228+
impl<T> From<Buffer<T>> for PVector<T> {
229+
/// Creates a new [`PVector<T>`] from the given elements buffer, with an all valid validity.
230+
fn from(value: Buffer<T>) -> Self {
231+
let len = value.len();
232+
Self {
233+
elements: value,
234+
validity: Mask::new_true(len),
235+
}
236+
}
237+
}

0 commit comments

Comments
 (0)