• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vortex-data / vortex / 17045413678

18 Aug 2025 03:43PM UTC coverage: 86.065% (-1.8%) from 87.913%
17045413678

Pull #4215

github

web-flow
Merge 2657b4c8e into cb2220961
Pull Request #4215: Ji/vectors

136 of 1803 new or added lines in 42 files covered. (7.54%)

127 existing lines in 26 files now uncovered.

56918 of 66134 relevant lines covered (86.06%)

612050.14 hits per line

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

0.0
/vortex-vector/src/operators/compare.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use std::any::Any;
5
use std::marker::PhantomData;
6
use std::rc::Rc;
7
use std::task::Poll;
8

9
use itertools::Itertools;
10
use vortex_dtype::{NativePType, match_each_native_ptype};
11
use vortex_error::{VortexExpect, VortexResult, vortex_bail};
12

13
use crate::bits::BitView;
14
use crate::operators::constant::ConstantOperator;
15
use crate::operators::scalar_compare::ScalarCompareOperator;
16
use crate::operators::{BindContext, Operator};
17
use crate::types::{Element, VType};
18
use crate::vector::VectorId;
19
use crate::view::ViewMut;
20
use crate::{Kernel, KernelContext};
21

22
// TODO(joe): dedup.
23
// This duplicates the Operator from vortex_array,
24
// make we can merge them into here, or another package
25
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
26
pub enum BinaryOperator {
27
    /// Equality (`=`)
28
    Eq,
29
    /// Inequality (`!=`)
30
    NotEq,
31
    /// Greater than (`>`)
32
    Gt,
33
    /// Greater than or equal (`>=`)
34
    Gte,
35
    /// Less than (`<`)
36
    Lt,
37
    /// Less than or equal (`<=`)
38
    Lte,
39
}
40

41
impl BinaryOperator {
NEW
42
    pub fn inverse(self) -> Self {
×
NEW
43
        match self {
×
NEW
44
            BinaryOperator::Eq => BinaryOperator::NotEq,
×
NEW
45
            BinaryOperator::NotEq => BinaryOperator::Eq,
×
NEW
46
            BinaryOperator::Gt => BinaryOperator::Lte,
×
NEW
47
            BinaryOperator::Gte => BinaryOperator::Lt,
×
NEW
48
            BinaryOperator::Lt => BinaryOperator::Gte,
×
NEW
49
            BinaryOperator::Lte => BinaryOperator::Gt,
×
50
        }
NEW
51
    }
×
52
}
53

54
#[macro_export]
55
macro_rules! match_each_compare_op {
56
    ($self:expr, | $enc:ident | $body:block) => {{
57
        match $self {
58
            BinaryOperator::Eq => {
59
                type $enc = $crate::operators::compare::Eq;
60
                $body
61
            }
62
            BinaryOperator::NotEq => {
63
                type $enc = $crate::operators::compare::NotEq;
64
                $body
65
            }
66
            BinaryOperator::Gt => {
67
                type $enc = $crate::operators::compare::Gt;
68
                $body
69
            }
70
            BinaryOperator::Gte => {
71
                type $enc = $crate::operators::compare::Gte;
72
                $body
73
            }
74
            BinaryOperator::Lt => {
75
                type $enc = $crate::operators::compare::Lt;
76
                $body
77
            }
78
            BinaryOperator::Lte => {
79
                type $enc = $crate::operators::compare::Lte;
80
                $body
81
            }
82
        }
83
    }};
84
}
85

86
#[derive(Debug, Hash)]
87
pub struct CompareOperator {
88
    children: [Rc<dyn Operator>; 2],
89
    op: BinaryOperator,
90
}
91

92
impl CompareOperator {
NEW
93
    pub fn new(lhs: Rc<dyn Operator>, rhs: Rc<dyn Operator>, op: BinaryOperator) -> Self {
×
NEW
94
        assert_eq!(lhs.vtype(), rhs.vtype(), "Operands must have the same type");
×
NEW
95
        Self {
×
NEW
96
            children: [lhs, rhs],
×
NEW
97
            op,
×
NEW
98
        }
×
NEW
99
    }
×
100
}
101

102
impl Operator for CompareOperator {
NEW
103
    fn as_any(&self) -> &dyn Any {
×
NEW
104
        self
×
NEW
105
    }
×
106

NEW
107
    fn vtype(&self) -> VType {
×
NEW
108
        VType::Bool
×
NEW
109
    }
×
110

NEW
111
    fn children(&self) -> &[Rc<dyn Operator>] {
×
NEW
112
        &self.children
×
NEW
113
    }
×
114

NEW
115
    fn with_children(&self, children: Vec<Rc<dyn Operator>>) -> Rc<dyn Operator> {
×
NEW
116
        let [lhs, rhs] = children
×
NEW
117
            .try_into()
×
NEW
118
            .ok()
×
NEW
119
            .vortex_expect("Expected 2 children");
×
NEW
120
        Rc::new(CompareOperator::new(lhs, rhs, self.op))
×
NEW
121
    }
×
122

NEW
123
    fn bind(&self, ctx: &dyn BindContext) -> VortexResult<Box<dyn Kernel>> {
×
NEW
124
        assert_eq!(self.children[0].vtype(), self.children[1].vtype());
×
125

NEW
126
        match self.children[0].vtype() {
×
NEW
127
            VType::Primitive(ptype) => {
×
NEW
128
                match_each_native_ptype!(ptype, |T| {
×
NEW
129
                    match_each_compare_op!(self.op, |Op| {
×
NEW
130
                        Ok(Box::new(ComparePrimitiveKernel::<T, Op> {
×
NEW
131
                            lhs: ctx.children()[0],
×
NEW
132
                            rhs: ctx.children()[1],
×
NEW
133
                            _phantom: PhantomData,
×
NEW
134
                        }) as Box<dyn Kernel>)
×
135
                    })
136
                })
137
            }
NEW
138
            _ => vortex_bail!(
×
NEW
139
                "Unsupported type for comparison: {}",
×
NEW
140
                self.children[0].vtype()
×
141
            ),
142
        }
NEW
143
    }
×
144

NEW
145
    fn reduce_children(&self, children: &[Rc<dyn Operator>]) -> Option<Rc<dyn Operator>> {
×
NEW
146
        let constants = children
×
NEW
147
            .iter()
×
NEW
148
            .enumerate()
×
NEW
149
            .filter_map(|(idx, c)| {
×
NEW
150
                c.as_any()
×
NEW
151
                    .downcast_ref::<ConstantOperator>()
×
NEW
152
                    .map(|c| (idx, c))
×
NEW
153
            })
×
NEW
154
            .collect_vec();
×
155

NEW
156
        if constants.len() != 1 {
×
NEW
157
            return None;
×
NEW
158
        }
×
NEW
159
        let [(idx, lhs)] = constants
×
NEW
160
            .try_into()
×
NEW
161
            .ok()
×
NEW
162
            .vortex_expect("Expected 1 constant");
×
163

NEW
164
        if idx == 0 {
×
NEW
165
            Some(Rc::new(ScalarCompareOperator::new(
×
NEW
166
                children[1].clone(),
×
NEW
167
                self.op.inverse(),
×
NEW
168
                lhs.scalar.clone(),
×
NEW
169
            )))
×
170
        } else {
NEW
171
            Some(Rc::new(ScalarCompareOperator::new(
×
NEW
172
                children[0].clone(),
×
NEW
173
                self.op,
×
NEW
174
                lhs.scalar.clone(),
×
NEW
175
            )))
×
176
        }
NEW
177
    }
×
178
}
179

180
/// A compare operator for primitive types that compares two vectors element-wise using a binary
181
/// operation.
182
pub struct ComparePrimitiveKernel<T, Op> {
183
    lhs: VectorId,
184
    rhs: VectorId,
185
    _phantom: PhantomData<(T, Op)>,
186
}
187

188
impl<T: Element + NativePType, Op: CompareOp<T>> Kernel for ComparePrimitiveKernel<T, Op> {
NEW
189
    fn seek(&mut self, chunk_idx: usize) -> VortexResult<()> {
×
NEW
190
        todo!()
×
191
    }
192

NEW
193
    fn step(
×
NEW
194
        &mut self,
×
NEW
195
        ctx: &dyn KernelContext,
×
NEW
196
        selected: BitView,
×
NEW
197
        out: &mut ViewMut,
×
NEW
198
    ) -> Poll<VortexResult<()>> {
×
NEW
199
        let lhs_vec = ctx.vector(self.lhs);
×
NEW
200
        let lhs = lhs_vec.as_slice::<T>();
×
NEW
201
        let rhs_vec = ctx.vector(self.rhs);
×
NEW
202
        let rhs = rhs_vec.as_slice::<T>();
×
NEW
203
        let bools = out.as_slice_mut::<bool>();
×
204

NEW
205
        assert_eq!(
×
NEW
206
            lhs.len(),
×
NEW
207
            rhs.len(),
×
NEW
208
            "LHS and RHS must have the same length"
×
209
        );
210

NEW
211
        for i in 0..selected.true_count() {
×
NEW
212
            bools[i] = unsafe { Op::compare(lhs.get_unchecked(i), rhs.get_unchecked(i)) };
×
NEW
213
        }
×
214

NEW
215
        Poll::Ready(Ok(()))
×
NEW
216
    }
×
217
}
218

219
pub(crate) trait CompareOp<T> {
220
    fn compare(lhs: &T, rhs: &T) -> bool;
221
}
222

223
pub struct Eq;
224
impl<T: PartialEq> CompareOp<T> for Eq {
225
    #[inline(always)]
NEW
226
    fn compare(lhs: &T, rhs: &T) -> bool {
×
NEW
227
        lhs == rhs
×
NEW
228
    }
×
229
}
230

231
pub struct NotEq;
232
impl<T: PartialEq> CompareOp<T> for NotEq {
233
    #[inline(always)]
NEW
234
    fn compare(lhs: &T, rhs: &T) -> bool {
×
NEW
235
        lhs != rhs
×
NEW
236
    }
×
237
}
238

239
pub struct Gt;
240
impl<T: PartialOrd> CompareOp<T> for Gt {
241
    #[inline(always)]
NEW
242
    fn compare(lhs: &T, rhs: &T) -> bool {
×
NEW
243
        lhs > rhs
×
NEW
244
    }
×
245
}
246

247
pub struct Gte;
248
impl<T: PartialOrd> CompareOp<T> for Gte {
249
    #[inline(always)]
NEW
250
    fn compare(lhs: &T, rhs: &T) -> bool {
×
NEW
251
        lhs >= rhs
×
NEW
252
    }
×
253
}
254

255
pub struct Lt;
256
impl<T: PartialOrd> CompareOp<T> for Lt {
257
    #[inline(always)]
NEW
258
    fn compare(lhs: &T, rhs: &T) -> bool {
×
NEW
259
        lhs < rhs
×
NEW
260
    }
×
261
}
262

263
pub struct Lte;
264
impl<T: PartialOrd> CompareOp<T> for Lte {
265
    #[inline(always)]
NEW
266
    fn compare(lhs: &T, rhs: &T) -> bool {
×
NEW
267
        lhs <= rhs
×
NEW
268
    }
×
269
}
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