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

vortex-data / vortex / 16204612549

10 Jul 2025 07:50PM UTC coverage: 81.152% (+2.9%) from 78.263%
16204612549

Pull #3825

github

web-flow
Merge d0d2717da into be9c2fd3e
Pull Request #3825: feat: Add optimize ArrayOp with VBView implementation

178 of 211 new or added lines in 4 files covered. (84.36%)

330 existing lines in 34 files now uncovered.

45433 of 55985 relevant lines covered (81.15%)

145951.87 hits per line

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

58.82
/vortex-expr/src/exprs/not.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use std::fmt::Display;
5
use std::hash::Hash;
6

7
use vortex_array::compute::invert;
8
use vortex_array::{ArrayRef, DeserializeMetadata, EmptyMetadata};
9
use vortex_dtype::DType;
10
use vortex_error::{VortexResult, vortex_bail};
11

12
use crate::{AnalysisExpr, ExprEncodingRef, ExprId, ExprRef, IntoExpr, Scope, VTable, vtable};
13

14
vtable!(Not);
15

16
#[allow(clippy::derived_hash_with_manual_eq)]
17
#[derive(Clone, Debug, Hash)]
18
pub struct NotExpr {
19
    child: ExprRef,
20
}
21

22
impl PartialEq for NotExpr {
UNCOV
23
    fn eq(&self, other: &Self) -> bool {
×
UNCOV
24
        self.child.eq(&other.child)
×
25
    }
×
26
}
27

28
pub struct NotExprEncoding;
29

30
impl VTable for NotVTable {
31
    type Expr = NotExpr;
32
    type Encoding = NotExprEncoding;
33
    type Metadata = EmptyMetadata;
34

35
    fn id(_encoding: &Self::Encoding) -> ExprId {
123✔
36
        ExprId::new_ref("not")
123✔
37
    }
123✔
38

UNCOV
39
    fn encoding(_expr: &Self::Expr) -> ExprEncodingRef {
×
UNCOV
40
        ExprEncodingRef::new_ref(NotExprEncoding.as_ref())
×
41
    }
×
42

43
    fn metadata(_expr: &Self::Expr) -> Option<Self::Metadata> {
×
UNCOV
44
        Some(EmptyMetadata)
×
45
    }
×
46

47
    fn children(expr: &Self::Expr) -> Vec<&ExprRef> {
×
UNCOV
48
        vec![&expr.child]
×
49
    }
×
50

51
    fn with_children(_expr: &Self::Expr, children: Vec<ExprRef>) -> VortexResult<Self::Expr> {
×
UNCOV
52
        Ok(NotExpr::new(children[0].clone()))
×
53
    }
×
54

55
    fn build(
×
UNCOV
56
        _encoding: &Self::Encoding,
×
57
        _metadata: &<Self::Metadata as DeserializeMetadata>::Output,
×
58
        children: Vec<ExprRef>,
×
59
    ) -> VortexResult<Self::Expr> {
×
60
        if children.len() != 1 {
×
61
            vortex_bail!(
×
62
                "Not expression expects exactly one child, got {}",
×
63
                children.len()
×
64
            );
×
65
        }
×
66
        Ok(NotExpr::new(children[0].clone()))
×
67
    }
×
68

69
    fn evaluate(expr: &Self::Expr, scope: &Scope) -> VortexResult<ArrayRef> {
22✔
70
        let child_result = expr.child.unchecked_evaluate(scope)?;
22✔
71
        invert(&child_result)
22✔
72
    }
22✔
73

74
    fn return_dtype(expr: &Self::Expr, scope: &DType) -> VortexResult<DType> {
24✔
75
        let child = expr.child.return_dtype(scope)?;
24✔
76
        if !matches!(child, DType::Bool(_)) {
24✔
UNCOV
77
            vortex_bail!("Not expression expects a boolean child, got: {}", child);
×
78
        }
24✔
79
        Ok(child)
24✔
80
    }
24✔
81
}
82

83
impl NotExpr {
84
    pub fn new(child: ExprRef) -> Self {
25✔
85
        Self { child }
25✔
86
    }
25✔
87

UNCOV
88
    pub fn new_expr(child: ExprRef) -> ExprRef {
×
UNCOV
89
        Self::new(child).into_expr()
×
90
    }
×
91

92
    pub fn child(&self) -> &ExprRef {
×
UNCOV
93
        &self.child
×
94
    }
×
95
}
96

97
impl Display for NotExpr {
98
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1✔
99
        write!(f, "!{}", self.child)
1✔
100
    }
1✔
101
}
102

103
impl AnalysisExpr for NotExpr {}
104

105
pub fn not(operand: ExprRef) -> ExprRef {
25✔
106
    NotExpr::new(operand).into_expr()
25✔
107
}
25✔
108

109
#[cfg(test)]
110
mod tests {
111
    use vortex_array::ToCanonical;
112
    use vortex_array::arrays::BoolArray;
113
    use vortex_dtype::{DType, Nullability};
114

115
    use crate::{Scope, col, not, root, test_harness};
116

117
    #[test]
118
    fn invert_booleans() {
1✔
119
        let not_expr = not(root());
1✔
120
        let bools = BoolArray::from_iter([false, true, false, false, true, true]);
1✔
121
        assert_eq!(
1✔
122
            not_expr
1✔
123
                .evaluate(&Scope::new(bools.to_array()))
1✔
124
                .unwrap()
1✔
125
                .to_bool()
1✔
126
                .unwrap()
1✔
127
                .boolean_buffer()
1✔
128
                .iter()
1✔
129
                .collect::<Vec<_>>(),
1✔
130
            vec![true, false, true, true, false, false]
1✔
131
        );
1✔
132
    }
1✔
133

134
    #[test]
135
    fn dtype() {
1✔
136
        let not_expr = not(root());
1✔
137
        let dtype = DType::Bool(Nullability::NonNullable);
1✔
138
        assert_eq!(
1✔
139
            not_expr.return_dtype(&dtype).unwrap(),
1✔
140
            DType::Bool(Nullability::NonNullable)
1✔
141
        );
1✔
142

143
        let dtype = test_harness::struct_dtype();
1✔
144
        assert_eq!(
1✔
145
            not(col("bool1")).return_dtype(&dtype).unwrap(),
1✔
146
            DType::Bool(Nullability::NonNullable)
1✔
147
        );
1✔
148
    }
1✔
149
}
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