vortex_fastlanes/delta/compute/
cast.rs1use vortex_array::ArrayRef;
5use vortex_array::IntoArray;
6use vortex_array::compute::CastKernel;
7use vortex_array::compute::CastKernelAdapter;
8use vortex_array::compute::cast;
9use vortex_array::register_kernel;
10use vortex_dtype::DType;
11use vortex_dtype::Nullability::NonNullable;
12use vortex_error::VortexResult;
13use vortex_error::vortex_panic;
14
15use crate::delta::DeltaArray;
16use crate::delta::DeltaVTable;
17
18impl CastKernel for DeltaVTable {
19 fn cast(&self, array: &DeltaArray, dtype: &DType) -> VortexResult<Option<ArrayRef>> {
20 let DType::Primitive(target_ptype, _) = dtype else {
25 return Ok(None);
26 };
27
28 let DType::Primitive(source_ptype, _) = array.dtype() else {
29 vortex_panic!("delta should be primitive typed");
30 };
31
32 if target_ptype.is_signed_int() || source_ptype.bit_width() > target_ptype.bit_width() {
34 return Ok(None);
35 }
36
37 let casted_bases = cast(array.bases(), &dtype.with_nullability(NonNullable))?;
39 let casted_deltas = cast(array.deltas(), dtype)?;
40
41 Ok(Some(
43 DeltaArray::try_from_delta_compress_parts(casted_bases, casted_deltas)?.into_array(),
44 ))
45 }
46}
47
48register_kernel!(CastKernelAdapter(DeltaVTable).lift());
49
50#[cfg(test)]
51mod tests {
52 use rstest::rstest;
53 use vortex_array::ToCanonical;
54 use vortex_array::arrays::PrimitiveArray;
55 use vortex_array::assert_arrays_eq;
56 use vortex_array::compute::cast;
57 use vortex_array::compute::conformance::cast::test_cast_conformance;
58 use vortex_buffer::Buffer;
59 use vortex_dtype::DType;
60 use vortex_dtype::Nullability;
61 use vortex_dtype::PType;
62
63 use crate::delta::DeltaArray;
64
65 #[test]
66 fn test_cast_delta_u8_to_u32() {
67 let primitive = PrimitiveArray::new(
68 Buffer::copy_from(vec![10u8, 20, 30, 40, 50]),
69 vortex_array::validity::Validity::NonNullable,
70 );
71 let array = DeltaArray::try_from_primitive_array(&primitive).unwrap();
72
73 let casted = cast(
74 array.as_ref(),
75 &DType::Primitive(PType::U32, Nullability::NonNullable),
76 )
77 .unwrap();
78 assert_eq!(
79 casted.dtype(),
80 &DType::Primitive(PType::U32, Nullability::NonNullable)
81 );
82
83 let decoded = casted.to_primitive();
85 assert_arrays_eq!(decoded, PrimitiveArray::from_iter([10u32, 20, 30, 40, 50]));
86 }
87
88 #[test]
89 fn test_cast_delta_nullable() {
90 let values = PrimitiveArray::new(
93 Buffer::copy_from(vec![100u16, 0, 200, 300, 0]),
94 vortex_array::validity::Validity::NonNullable,
95 );
96 let array = DeltaArray::try_from_primitive_array(&values).unwrap();
97
98 let casted = cast(
99 array.as_ref(),
100 &DType::Primitive(PType::U32, Nullability::Nullable),
101 )
102 .unwrap();
103 assert_eq!(
104 casted.dtype(),
105 &DType::Primitive(PType::U32, Nullability::Nullable)
106 );
107 }
108
109 #[rstest]
110 #[case::u8(
111 PrimitiveArray::new(
112 Buffer::copy_from(vec![0u8, 10, 20, 30, 40, 50]),
113 vortex_array::validity::Validity::NonNullable,
114 )
115 )]
116 #[case::u16(
117 PrimitiveArray::new(
118 Buffer::copy_from(vec![0u16, 100, 200, 300, 400, 500]),
119 vortex_array::validity::Validity::NonNullable,
120 )
121 )]
122 #[case::u32(
123 PrimitiveArray::new(
124 Buffer::copy_from(vec![0u32, 1000, 2000, 3000, 4000]),
125 vortex_array::validity::Validity::NonNullable,
126 )
127 )]
128 #[case::u64(
129 PrimitiveArray::new(
130 Buffer::copy_from(vec![0u64, 10000, 20000, 30000]),
131 vortex_array::validity::Validity::NonNullable,
132 )
133 )]
134 fn test_cast_delta_conformance(#[case] primitive: PrimitiveArray) {
135 let delta_array = DeltaArray::try_from_primitive_array(&primitive).unwrap();
136 test_cast_conformance(delta_array.as_ref());
137 }
138}