vortex_array/arrays/decimal/compute/
take.rs1use vortex_buffer::Buffer;
5use vortex_error::VortexResult;
6
7use crate::ArrayRef;
8use crate::IntoArray;
9use crate::array::ArrayView;
10use crate::arrays::Decimal;
11use crate::arrays::DecimalArray;
12use crate::arrays::PrimitiveArray;
13use crate::arrays::dict::TakeExecute;
14use crate::dtype::IntegerPType;
15use crate::dtype::NativeDecimalType;
16use crate::executor::ExecutionCtx;
17use crate::match_each_decimal_value_type;
18use crate::match_each_integer_ptype;
19
20impl TakeExecute for Decimal {
21 fn take(
22 array: ArrayView<'_, Decimal>,
23 indices: &ArrayRef,
24 ctx: &mut ExecutionCtx,
25 ) -> VortexResult<Option<ArrayRef>> {
26 let indices = indices.clone().execute::<PrimitiveArray>(ctx)?;
27 let validity = array.validity()?.take(&indices.clone().into_array())?;
28
29 let decimal = match_each_decimal_value_type!(array.values_type(), |D| {
32 match_each_integer_ptype!(indices.ptype(), |I| {
33 let buffer =
34 take_to_buffer::<I, D>(indices.as_slice::<I>(), array.buffer::<D>().as_slice());
35 unsafe { DecimalArray::new_unchecked(buffer, array.decimal_dtype(), validity) }
38 })
39 });
40
41 Ok(Some(decimal.into_array()))
42 }
43}
44
45fn take_to_buffer<I: IntegerPType, T: NativeDecimalType>(indices: &[I], values: &[T]) -> Buffer<T> {
46 indices.iter().map(|idx| values[idx.as_()]).collect()
47}
48
49#[cfg(test)]
50mod tests {
51 use rstest::rstest;
52 use vortex_buffer::Buffer;
53 use vortex_buffer::buffer;
54
55 use crate::IntoArray;
56 use crate::VortexSessionExecute;
57 use crate::array_session;
58 use crate::arrays::DecimalArray;
59 use crate::arrays::PrimitiveArray;
60 use crate::assert_arrays_eq;
61 use crate::compute::conformance::take::test_take_conformance;
62 use crate::dtype::DecimalDType;
63 use crate::validity::Validity;
64
65 #[test]
66 fn test_take() {
67 let mut ctx = array_session().create_execution_ctx();
68 let ddtype = DecimalDType::new(19, 1);
69 let array = DecimalArray::new(
70 buffer![10i128, 11i128, 12i128, 13i128],
71 ddtype,
72 Validity::NonNullable,
73 );
74
75 let indices = buffer![0, 2, 3].into_array();
76 let taken = array.take(indices).unwrap();
77
78 let expected = DecimalArray::from_iter([10i128, 12, 13], ddtype);
79 assert_arrays_eq!(expected, taken, &mut ctx);
80 }
81
82 #[test]
83 fn test_take_null_indices() {
84 let mut ctx = array_session().create_execution_ctx();
85 let ddtype = DecimalDType::new(19, 1);
86 let array = DecimalArray::new(
87 buffer![i128::MAX, 11i128, 12i128, 13i128],
88 ddtype,
89 Validity::NonNullable,
90 );
91
92 let indices = PrimitiveArray::from_option_iter([None, Some(2), Some(3)]).into_array();
93 let taken = array.take(indices).unwrap();
94
95 let expected = DecimalArray::from_option_iter([None, Some(12i128), Some(13)], ddtype);
96 assert_arrays_eq!(expected, taken, &mut ctx);
97 }
98
99 #[rstest]
100 #[case(DecimalArray::new(
101 buffer![100i128, 200i128, 300i128, 400i128, 500i128],
102 DecimalDType::new(19, 2),
103 Validity::NonNullable,
104 ))]
105 #[case(DecimalArray::new(
106 buffer![10i64, 20i64, 30i64, 40i64, 50i64],
107 DecimalDType::new(10, 1),
108 Validity::NonNullable,
109 ))]
110 #[case(DecimalArray::new(
111 buffer![1i32, 2i32, 3i32, 4i32, 5i32],
112 DecimalDType::new(5, 0),
113 Validity::NonNullable,
114 ))]
115 #[case(DecimalArray::new(
116 buffer![1000i128, 2000i128, 3000i128, 4000i128, 5000i128],
117 DecimalDType::new(19, 3),
118 Validity::from_iter([true, false, true, true, false]),
119 ))]
120 #[case(DecimalArray::new(
121 buffer![42i128],
122 DecimalDType::new(19, 0),
123 Validity::NonNullable,
124 ))]
125 #[case({
126 let values: Vec<i128> = (0..100).map(|i| i * 1000).collect();
127 DecimalArray::new(
128 Buffer::from_iter(values),
129 DecimalDType::new(19, 4),
130 Validity::NonNullable,
131 )
132 })]
133 fn test_take_decimal_conformance(#[case] array: DecimalArray) {
134 test_take_conformance(&array.into_array());
135 }
136}