use vortex_array::DynArray;
use vortex_array::scalar::Scalar;
use vortex_array::vtable::OperationsVTable;
use vortex_error::VortexExpect;
use vortex_error::VortexResult;
use crate::ALPRD;
use crate::ALPRDArray;
impl OperationsVTable<ALPRD> for ALPRD {
fn scalar_at(array: &ALPRDArray, index: usize) -> VortexResult<Scalar> {
let maybe_patched_value = match array.left_parts_patches() {
Some(patches) => patches.get_patched(index)?,
None => None,
};
let left = match maybe_patched_value {
Some(patched_value) => patched_value
.as_primitive()
.as_::<u16>()
.vortex_expect("patched values must be non-null"),
_ => {
let left_code: u16 = array
.left_parts()
.scalar_at(index)?
.as_primitive()
.as_::<u16>()
.vortex_expect("left_code must be non-null");
array.left_parts_dictionary()[left_code as usize]
}
};
Ok(if array.is_f32() {
let right: u32 = array
.right_parts()
.scalar_at(index)?
.as_primitive()
.as_::<u32>()
.vortex_expect("non-null");
let packed = f32::from_bits((left as u32) << array.right_bit_width() | right);
Scalar::primitive(packed, array.dtype().nullability())
} else {
let right: u64 = array
.right_parts()
.scalar_at(index)?
.as_primitive()
.as_::<u64>()
.vortex_expect("non-null");
let packed = f64::from_bits(((left as u64) << array.right_bit_width()) | right);
Scalar::primitive(packed, array.dtype().nullability())
})
}
}
#[cfg(test)]
mod test {
use rstest::rstest;
use vortex_array::arrays::PrimitiveArray;
use vortex_array::assert_arrays_eq;
use vortex_array::scalar::Scalar;
use crate::ALPRDFloat;
use crate::RDEncoder;
#[rstest]
#[case(0.1f32, 0.2f32, 3e25f32)]
#[case(0.1f64, 0.2f64, 3e100f64)]
fn test_slice<T: ALPRDFloat>(#[case] a: T, #[case] b: T, #[case] outlier: T) {
let array = PrimitiveArray::from_iter([a, b, outlier]);
let encoded = RDEncoder::new(&[a, b]).encode(&array);
assert!(encoded.left_parts_patches().is_some());
assert_arrays_eq!(encoded, array);
}
#[rstest]
#[case(0.1f32, 0.2f32, 3e25f32)]
#[case(0.1f64, 0.2f64, 3e100f64)]
fn test_scalar_at<T: ALPRDFloat + Into<Scalar>>(
#[case] a: T,
#[case] b: T,
#[case] outlier: T,
) {
let array = PrimitiveArray::from_iter([a, b, outlier]);
let encoded = RDEncoder::new(&[a, b]).encode(&array);
assert!(encoded.left_parts_patches().is_some());
assert_arrays_eq!(encoded, array);
}
#[test]
fn nullable_scalar_at() {
let a = 0.1f64;
let b = 0.2f64;
let outlier = 3e100f64;
let array = PrimitiveArray::from_option_iter([Some(a), Some(b), Some(outlier)]);
let encoded = RDEncoder::new(&[a, b]).encode(&array);
assert!(encoded.left_parts_patches().is_some());
assert_arrays_eq!(
encoded,
PrimitiveArray::from_option_iter([Some(a), Some(b), Some(outlier)])
);
}
}