• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

vortex-data / vortex / 16277982668

14 Jul 2025 09:12PM UTC coverage: 81.564% (+0.4%) from 81.147%
16277982668

Pull #3852

github

web-flow
Merge e78f6e62e into b0be264bf
Pull Request #3852: feat: call optimize in compressor

3 of 3 new or added lines in 1 file covered. (100.0%)

381 existing lines in 36 files now uncovered.

46289 of 56752 relevant lines covered (81.56%)

157514.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.75
/vortex-array/src/compute/cast.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use std::sync::LazyLock;
5

6
use arcref::ArcRef;
7
use vortex_dtype::DType;
8
use vortex_error::{VortexError, VortexResult, vortex_bail, vortex_err};
9

10
use crate::compute::{ComputeFn, ComputeFnVTable, InvocationArgs, Kernel, Output};
11
use crate::vtable::VTable;
12
use crate::{Array, ArrayRef};
13

14
/// Attempt to cast an array to a desired DType.
15
///
16
/// Some array support the ability to narrow or upcast.
17
pub fn cast(array: &dyn Array, dtype: &DType) -> VortexResult<ArrayRef> {
19,446✔
18
    CAST_FN
19,446✔
19
        .invoke(&InvocationArgs {
19,446✔
20
            inputs: &[array.into(), dtype.into()],
19,446✔
21
            options: &(),
19,446✔
22
        })?
19,446✔
23
        .unwrap_array()
17,993✔
24
}
19,446✔
25

26
pub static CAST_FN: LazyLock<ComputeFn> = LazyLock::new(|| {
5,105✔
27
    let compute = ComputeFn::new("cast".into(), ArcRef::new_ref(&Cast));
5,105✔
28
    for kernel in inventory::iter::<CastKernelRef> {
53,608✔
29
        compute.register_kernel(kernel.0.clone());
48,503✔
30
    }
48,503✔
31
    compute
5,105✔
32
});
5,105✔
33

34
struct Cast;
35

36
impl ComputeFnVTable for Cast {
37
    fn invoke(
19,446✔
38
        &self,
19,446✔
39
        args: &InvocationArgs,
19,446✔
40
        kernels: &[ArcRef<dyn Kernel>],
19,446✔
41
    ) -> VortexResult<Output> {
19,446✔
42
        let CastArgs { array, dtype } = CastArgs::try_from(args)?;
19,446✔
43

44
        if array.dtype() == dtype {
19,446✔
45
            return Ok(array.to_array().into());
9,729✔
46
        }
9,717✔
47

48
        // TODO(ngates): check for null_count if dtype is non-nullable
49

50
        for kernel in kernels {
30,620✔
51
            if let Some(output) = kernel.invoke(args)? {
29,664✔
52
                return Ok(output);
8,030✔
53
            }
20,903✔
54
        }
55
        if let Some(output) = array.invoke(&CAST_FN, args)? {
956✔
56
            return Ok(output);
×
57
        }
956✔
58

956✔
59
        // Otherwise, we fall back to the canonical implementations.
956✔
60
        log::debug!(
956✔
61
            "Falling back to canonical cast for encoding {} and dtype {} to {}",
×
62
            array.encoding_id(),
×
63
            array.dtype(),
×
64
            dtype
65
        );
66

67
        if array.is_canonical() {
956✔
68
            vortex_bail!(
74✔
69
                "No compute kernel to cast array {} with dtype {} to {}",
74✔
70
                array.encoding_id(),
74✔
71
                array.dtype(),
74✔
72
                dtype
74✔
73
            );
74✔
74
        }
882✔
75

882✔
76
        Ok(cast(array.to_canonical()?.as_ref(), dtype)?.into())
882✔
77
    }
19,446✔
78

79
    fn return_dtype(&self, args: &InvocationArgs) -> VortexResult<DType> {
19,446✔
80
        let CastArgs { dtype, .. } = CastArgs::try_from(args)?;
19,446✔
81
        Ok(dtype.clone())
19,446✔
82
    }
19,446✔
83

84
    fn return_len(&self, args: &InvocationArgs) -> VortexResult<usize> {
19,446✔
85
        let CastArgs { array, .. } = CastArgs::try_from(args)?;
19,446✔
86
        Ok(array.len())
19,446✔
87
    }
19,446✔
88

89
    fn is_elementwise(&self) -> bool {
19,446✔
90
        true
19,446✔
91
    }
19,446✔
92
}
93

94
struct CastArgs<'a> {
95
    array: &'a dyn Array,
96
    dtype: &'a DType,
97
}
98

99
impl<'a> TryFrom<&InvocationArgs<'a>> for CastArgs<'a> {
100
    type Error = VortexError;
101

102
    fn try_from(args: &InvocationArgs<'a>) -> Result<Self, Self::Error> {
88,002✔
103
        if args.inputs.len() != 2 {
88,002✔
104
            vortex_bail!(
×
105
                "Cast function requires 2 arguments, but got {}",
×
UNCOV
106
                args.inputs.len()
×
UNCOV
107
            );
×
108
        }
88,002✔
109
        let array = args.inputs[0]
88,002✔
110
            .array()
88,002✔
111
            .ok_or_else(|| vortex_err!("Missing array argument"))?;
88,002✔
112
        let dtype = args.inputs[1]
88,002✔
113
            .dtype()
88,002✔
114
            .ok_or_else(|| vortex_err!("Missing dtype argument"))?;
88,002✔
115

116
        Ok(CastArgs { array, dtype })
88,002✔
117
    }
88,002✔
118
}
119

120
pub struct CastKernelRef(ArcRef<dyn Kernel>);
121
inventory::collect!(CastKernelRef);
122

123
pub trait CastKernel: VTable {
124
    fn cast(&self, array: &Self::Array, dtype: &DType) -> VortexResult<Option<ArrayRef>>;
125
}
126

127
#[derive(Debug)]
128
pub struct CastKernelAdapter<V: VTable>(pub V);
129

130
impl<V: VTable + CastKernel> CastKernelAdapter<V> {
131
    pub const fn lift(&'static self) -> CastKernelRef {
×
UNCOV
132
        CastKernelRef(ArcRef::new_ref(self))
×
UNCOV
133
    }
×
134
}
135

136
impl<V: VTable + CastKernel> Kernel for CastKernelAdapter<V> {
137
    fn invoke(&self, args: &InvocationArgs) -> VortexResult<Option<Output>> {
28,824✔
138
        let CastArgs { array, dtype } = CastArgs::try_from(args)?;
28,824✔
139
        let Some(array) = array.as_opt::<V>() else {
28,824✔
140
            return Ok(None);
19,551✔
141
        };
142

143
        Ok(V::cast(&self.0, array, dtype)?.map(|o| o.into()))
9,273✔
144
    }
28,824✔
145
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc