vortex_alp/alp_rd/compute/
take.rs1use vortex_array::ArrayRef;
5use vortex_array::ArrayView;
6use vortex_array::ExecutionCtx;
7use vortex_array::IntoArray;
8use vortex_array::arrays::dict::TakeExecute;
9use vortex_array::builtins::ArrayBuiltins;
10use vortex_array::scalar::Scalar;
11use vortex_error::VortexResult;
12
13use crate::ALPRD;
14use crate::ALPRDArrayExt;
15use crate::ALPRDArraySlotsExt;
16
17impl TakeExecute for ALPRD {
18 fn take(
19 array: ArrayView<'_, Self>,
20 indices: &ArrayRef,
21 ctx: &mut ExecutionCtx,
22 ) -> VortexResult<Option<ArrayRef>> {
23 let taken_left_parts = array.left_parts().take(indices.clone())?;
24 let exceptions_dtype = taken_left_parts.dtype().as_nonnullable();
29 let left_parts_exceptions = array
30 .left_parts_patches()
31 .map(|patches| {
32 patches
33 .take(indices, ctx)?
34 .map(|taken| taken.map_values(|values| values.cast(exceptions_dtype.clone())))
35 .transpose()
36 })
37 .transpose()?
38 .flatten();
39 let right_parts = array
40 .right_parts()
41 .take(indices.clone())?
42 .fill_null(Scalar::zero_value(array.right_parts().dtype()))?;
43
44 Ok(Some(
45 ALPRD::try_new(
46 array
47 .dtype()
48 .with_nullability(taken_left_parts.dtype().nullability()),
49 taken_left_parts,
50 array.left_parts_dictionary().clone(),
51 right_parts,
52 array.right_bit_width(),
53 left_parts_exceptions,
54 )?
55 .into_array(),
56 ))
57 }
58}
59
60#[cfg(test)]
61mod test {
62 use std::sync::LazyLock;
63
64 use rstest::rstest;
65 use vortex_array::IntoArray;
66 use vortex_array::VortexSessionExecute;
67 use vortex_array::array_session;
68 use vortex_array::arrays::PrimitiveArray;
69 use vortex_array::assert_arrays_eq;
70 use vortex_array::compute::conformance::take::test_take_conformance;
71 use vortex_session::VortexSession;
72
73 use crate::ALPRDArrayExt;
74 use crate::ALPRDFloat;
75 use crate::RDEncoder;
76
77 static SESSION: LazyLock<VortexSession> = LazyLock::new(|| {
78 let session = array_session();
79 crate::initialize(&session);
80 session
81 });
82
83 #[rstest]
84 #[case(0.1f32, 0.2f32, 3e25f32)]
85 #[case(0.1f64, 0.2f64, 3e100f64)]
86 fn test_take<T: ALPRDFloat>(#[case] a: T, #[case] b: T, #[case] outlier: T) {
87 use vortex_array::IntoArray as _;
88 use vortex_buffer::buffer;
89
90 let mut ctx = SESSION.create_execution_ctx();
91 let array = PrimitiveArray::from_iter([a, b, outlier]);
92 let encoded = RDEncoder::new(&[a, b]).encode(array.as_view());
93
94 assert!(encoded.left_parts_patches().is_some());
95 assert!(
96 encoded
97 .left_parts_patches()
98 .unwrap()
99 .dtype()
100 .is_unsigned_int()
101 );
102
103 let taken = encoded
104 .take(buffer![0, 2].into_array())
105 .unwrap()
106 .execute::<PrimitiveArray>(&mut ctx)
107 .unwrap();
108
109 assert_arrays_eq!(taken, PrimitiveArray::from_iter([a, outlier]), &mut ctx);
110 }
111
112 #[rstest]
113 #[case(0.1f32, 0.2f32, 3e25f32)]
114 #[case(0.1f64, 0.2f64, 3e100f64)]
115 fn take_with_nulls<T: ALPRDFloat>(#[case] a: T, #[case] b: T, #[case] outlier: T) {
116 let mut ctx = SESSION.create_execution_ctx();
117 let array = PrimitiveArray::from_iter([a, b, outlier]);
118 let encoded = RDEncoder::new(&[a, b]).encode(array.as_view());
119
120 assert!(encoded.left_parts_patches().is_some());
121 assert!(
122 encoded
123 .left_parts_patches()
124 .unwrap()
125 .dtype()
126 .is_unsigned_int()
127 );
128
129 let taken = encoded
130 .take(PrimitiveArray::from_option_iter([Some(0), Some(2), None]).into_array())
131 .unwrap()
132 .execute::<PrimitiveArray>(&mut ctx)
133 .unwrap();
134
135 assert_arrays_eq!(
136 taken,
137 PrimitiveArray::from_option_iter([Some(a), Some(outlier), None]),
138 &mut ctx
139 );
140 }
141
142 #[rstest]
143 #[case(0.1f32, 0.2f32, 3e25f32)]
144 #[case(0.1f64, 0.2f64, 3e100f64)]
145 fn test_take_conformance_alprd<T: ALPRDFloat>(#[case] a: T, #[case] b: T, #[case] outlier: T) {
146 let mut ctx = SESSION.create_execution_ctx();
147 test_take_conformance(
148 &RDEncoder::new(&[a, b])
149 .encode(PrimitiveArray::from_iter([a, b, outlier, b, outlier]).as_view())
150 .into_array(),
151 &mut ctx,
152 );
153 }
154
155 #[rstest]
156 #[case(0.1f32, 3e25f32)]
157 #[case(0.5f64, 1e100f64)]
158 fn test_take_with_nulls_conformance<T: ALPRDFloat>(#[case] a: T, #[case] outlier: T) {
159 let mut ctx = SESSION.create_execution_ctx();
160 test_take_conformance(
161 &RDEncoder::new(&[a])
162 .encode(
163 PrimitiveArray::from_option_iter([Some(a), None, Some(outlier), Some(a), None])
164 .as_view(),
165 )
166 .into_array(),
167 &mut ctx,
168 );
169 }
170}