vortex_array/arrays/constant/compute/
take.rs1use vortex_error::VortexResult;
5
6use crate::ArrayRef;
7use crate::IntoArray;
8use crate::array::ArrayView;
9use crate::arrays::Constant;
10use crate::arrays::ConstantArray;
11use crate::arrays::MaskedArray;
12use crate::arrays::dict::TakeReduce;
13use crate::arrays::dict::TakeReduceAdaptor;
14use crate::optimizer::rules::ParentRuleSet;
15use crate::scalar::Scalar;
16use crate::validity::Validity;
17
18impl TakeReduce for Constant {
19 fn take(array: ArrayView<'_, Constant>, indices: &ArrayRef) -> VortexResult<Option<ArrayRef>> {
20 let result = match indices.validity()? {
21 Validity::NonNullable | Validity::AllValid => {
22 let scalar = Scalar::try_new(
23 array
24 .scalar()
25 .dtype()
26 .union_nullability(indices.dtype().nullability()),
27 array.scalar().value().cloned(),
28 )?;
29 ConstantArray::new(scalar, indices.len()).into_array()
30 }
31 Validity::AllInvalid => ConstantArray::new(
32 Scalar::null(
33 array
34 .dtype()
35 .union_nullability(indices.dtype().nullability()),
36 ),
37 indices.len(),
38 )
39 .into_array(),
40 validity @ Validity::Array(_) => {
41 let arr = ConstantArray::new(array.scalar().clone(), indices.len()).into_array();
42
43 if array.scalar().is_null() {
44 return Ok(Some(arr));
45 }
46
47 unsafe { MaskedArray::new_unchecked(arr, validity) }.into_array()
50 }
51 };
52 Ok(Some(result))
53 }
54}
55
56impl Constant {
57 pub const TAKE_RULES: ParentRuleSet<Self> =
58 ParentRuleSet::new(&[ParentRuleSet::lift(&TakeReduceAdaptor::<Self>(Self))]);
59}
60
61#[cfg(test)]
62mod tests {
63 use std::f64;
64
65 use rstest::rstest;
66 use vortex_buffer::buffer;
67 use vortex_mask::AllOr;
68
69 use crate::IntoArray;
70 use crate::VortexSessionExecute;
71 use crate::array_session;
72 use crate::arrays::ConstantArray;
73 use crate::arrays::PrimitiveArray;
74 use crate::assert_arrays_eq;
75 use crate::compute::conformance::take::test_take_conformance;
76 use crate::dtype::Nullability;
77 use crate::scalar::Scalar;
78 use crate::validity::Validity;
79
80 #[test]
81 fn take_nullable_indices() {
82 let mut ctx = array_session().create_execution_ctx();
83 let array = ConstantArray::new(42, 10).into_array();
84 let taken = array
85 .take(
86 PrimitiveArray::new(
87 buffer![0, 5, 7],
88 Validity::from_iter(vec![false, true, false]),
89 )
90 .into_array(),
91 )
92 .unwrap();
93 let valid_indices: &[usize] = &[1usize];
94 assert_eq!(
95 &array.dtype().with_nullability(Nullability::Nullable),
96 taken.dtype()
97 );
98 assert_arrays_eq!(
99 taken,
100 PrimitiveArray::new(
101 buffer![42i32, 42, 42],
102 Validity::from_iter([false, true, false])
103 ),
104 &mut ctx
105 );
106 assert_eq!(
107 taken
108 .validity()
109 .unwrap()
110 .execute_mask(taken.len(), &mut ctx)
111 .unwrap()
112 .indices(),
113 AllOr::Some(valid_indices)
114 );
115 }
116
117 #[test]
118 fn take_all_valid_indices() {
119 let mut ctx = array_session().create_execution_ctx();
120 let array = ConstantArray::new(42, 10).into_array();
121 let taken = array
122 .take(PrimitiveArray::new(buffer![0, 5, 7], Validity::AllValid).into_array())
123 .unwrap();
124 assert_eq!(
125 &array.dtype().with_nullability(Nullability::Nullable),
126 taken.dtype()
127 );
128 assert_arrays_eq!(
129 taken,
130 PrimitiveArray::new(buffer![42i32, 42, 42], Validity::AllValid),
131 &mut ctx
132 );
133 assert_eq!(
134 taken
135 .validity()
136 .unwrap()
137 .execute_mask(taken.len(), &mut ctx)
138 .unwrap()
139 .indices(),
140 AllOr::All
141 );
142 }
143
144 #[rstest]
145 #[case(ConstantArray::new(42i32, 5))]
146 #[case(ConstantArray::new(f64::consts::PI, 10))]
147 #[case(ConstantArray::new(Scalar::from("hello"), 3))]
148 #[case(ConstantArray::new(Scalar::null_native::<i64>(), 5))]
149 #[case(ConstantArray::new(true, 1))]
150 fn test_take_constant_conformance(#[case] array: ConstantArray) {
151 test_take_conformance(
152 &array.into_array(),
153 &mut array_session().create_execution_ctx(),
154 );
155 }
156}