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_array::dtype::NativePType;
72 use vortex_session::VortexSession;
73
74 use crate::ALPRDArrayExt;
75 use crate::ALPRDFloat;
76 use crate::RDEncoder;
77 use crate::RDEncoderExt;
78
79 static SESSION: LazyLock<VortexSession> = LazyLock::new(|| {
80 let session = array_session();
81 crate::initialize(&session);
82 session
83 });
84
85 #[rstest]
86 #[case(0.1f32, 0.2f32, 3e25f32)]
87 #[case(0.1f64, 0.2f64, 3e100f64)]
88 fn test_take<T: ALPRDFloat + NativePType>(#[case] a: T, #[case] b: T, #[case] outlier: T) {
89 use vortex_array::IntoArray as _;
90 use vortex_buffer::buffer;
91
92 let mut ctx = SESSION.create_execution_ctx();
93 let array = PrimitiveArray::from_iter([a, b, outlier]);
94 let encoded = RDEncoder::new(&[a, b]).encode(array.as_view());
95
96 assert!(encoded.left_parts_patches().is_some());
97 assert!(
98 encoded
99 .left_parts_patches()
100 .unwrap()
101 .dtype()
102 .is_unsigned_int()
103 );
104
105 let taken = encoded.take(buffer![0, 2].into_array()).unwrap();
106
107 assert_arrays_eq!(taken, PrimitiveArray::from_iter([a, outlier]), &mut ctx);
108 }
109
110 #[rstest]
111 #[case(0.1f32, 0.2f32, 3e25f32)]
112 #[case(0.1f64, 0.2f64, 3e100f64)]
113 fn take_with_nulls<T: ALPRDFloat + NativePType>(
114 #[case] a: T,
115 #[case] b: T,
116 #[case] outlier: T,
117 ) {
118 let mut ctx = SESSION.create_execution_ctx();
119 let array = PrimitiveArray::from_iter([a, b, outlier]);
120 let encoded = RDEncoder::new(&[a, b]).encode(array.as_view());
121
122 assert!(encoded.left_parts_patches().is_some());
123 assert!(
124 encoded
125 .left_parts_patches()
126 .unwrap()
127 .dtype()
128 .is_unsigned_int()
129 );
130
131 let taken = encoded
132 .take(PrimitiveArray::from_option_iter([Some(0), Some(2), None]).into_array())
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 + NativePType>(
146 #[case] a: T,
147 #[case] b: T,
148 #[case] outlier: T,
149 ) {
150 let mut ctx = SESSION.create_execution_ctx();
151 test_take_conformance(
152 &RDEncoder::new(&[a, b])
153 .encode(PrimitiveArray::from_iter([a, b, outlier, b, outlier]).as_view())
154 .into_array(),
155 &mut ctx,
156 );
157 }
158
159 #[rstest]
160 #[case(0.1f32, 3e25f32)]
161 #[case(0.5f64, 1e100f64)]
162 fn test_take_with_nulls_conformance<T: ALPRDFloat + NativePType>(
163 #[case] a: T,
164 #[case] outlier: T,
165 ) {
166 let mut ctx = SESSION.create_execution_ctx();
167 test_take_conformance(
168 &RDEncoder::new(&[a])
169 .encode(
170 PrimitiveArray::from_option_iter([Some(a), None, Some(outlier), Some(a), None])
171 .as_view(),
172 )
173 .into_array(),
174 &mut ctx,
175 );
176 }
177}