@@ -40,20 +40,44 @@ static bool op_and_bool(ref_t<T> x, bool xvalid, ref_t<T> y, bool yvalid, int8_t
40
40
return xvalid;
41
41
}
42
42
43
+
44
+ template <typename T>
45
+ static bool op_or_bool (ref_t <T> x, bool xvalid, ref_t <T> y, bool yvalid, int8_t * out)
46
+ {
47
+ if (x == 1 && xvalid) { // short-circuit
48
+ *out = 1 ;
49
+ return true ;
50
+ }
51
+ if (!yvalid) return false ;
52
+ if (y == 1 ) {
53
+ *out = 1 ;
54
+ return true ;
55
+ }
56
+ *out = 0 ;
57
+ return xvalid;
58
+ }
59
+
60
+
43
61
template <typename T>
44
62
inline static T op_and (T x, T y) {
45
63
return (x & y);
46
64
}
47
65
48
- class FExpr__and__ : public FExpr_BinaryOp {
66
+ template <typename T>
67
+ inline static T op_or (T x, T y) {
68
+ return (x | y);
69
+ }
70
+
71
+ template <bool AND>
72
+ class FExpr__andor__ : public FExpr_BinaryOp {
49
73
public:
50
74
using FExpr_BinaryOp::FExpr_BinaryOp;
51
75
using FExpr_BinaryOp::lhs_;
52
76
using FExpr_BinaryOp::rhs_;
53
77
54
78
55
- std::string name () const override { return " & " ; }
56
- int precedence () const noexcept override { return 4 ; }
79
+ std::string name () const override { return AND? " & " : " | " ; }
80
+ int precedence () const noexcept override { return AND? 4 : 3 ; }
57
81
58
82
59
83
Column evaluate1 (Column&& lcol, Column&& rcol) const override {
@@ -67,33 +91,47 @@ class FExpr__and__ : public FExpr_BinaryOp {
67
91
return Column::new_na_column (lcol.nrows (), SType::VOID);
68
92
}
69
93
if (stype1 == SType::BOOL && stype2 == SType::BOOL) {
94
+ if (AND) {
95
+ return Column (new FuncBinary2_ColumnImpl<int8_t , int8_t , int8_t >(
96
+ std::move (lcol), std::move (rcol),
97
+ op_and_bool<int8_t >,
98
+ nrows, SType::BOOL
99
+ ));
100
+ }
70
101
return Column (new FuncBinary2_ColumnImpl<int8_t , int8_t , int8_t >(
71
102
std::move (lcol), std::move (rcol),
72
- op_and_bool <int8_t >,
103
+ op_or_bool <int8_t >,
73
104
nrows, SType::BOOL
74
105
));
75
106
}
76
107
switch (stype0) {
77
- case SType::INT8: return make<int8_t >(std::move (lcol), std::move (rcol), stype0);
78
- case SType::INT16: return make<int16_t >(std::move (lcol), std::move (rcol), stype0);
79
- case SType::INT32: return make<int32_t >(std::move (lcol), std::move (rcol), stype0);
80
- case SType::INT64: return make<int64_t >(std::move (lcol), std::move (rcol), stype0);
108
+ case SType::INT8: return make<int8_t , AND >(std::move (lcol), std::move (rcol), stype0);
109
+ case SType::INT16: return make<int16_t , AND >(std::move (lcol), std::move (rcol), stype0);
110
+ case SType::INT32: return make<int32_t , AND >(std::move (lcol), std::move (rcol), stype0);
111
+ case SType::INT64: return make<int64_t , AND >(std::move (lcol), std::move (rcol), stype0);
81
112
default :
82
113
throw TypeError () << " Operator `&` cannot be applied to columns of "
83
114
" types `" << stype1 << " ` and `" << stype2 << " `" ;
84
115
}
85
116
}
86
117
87
118
private:
88
- template <typename T>
119
+ template <typename T, bool ANDD >
89
120
static Column make (Column&& a, Column&& b, SType stype) {
90
121
xassert (compatible_type<T>(stype));
91
122
size_t nrows = a.nrows ();
92
123
a.cast_inplace (stype);
93
124
b.cast_inplace (stype);
125
+ if (AND) {
126
+ return Column (new FuncBinary1_ColumnImpl<T, T, T>(
127
+ std::move (a), std::move (b),
128
+ op_and<T>,
129
+ nrows, stype
130
+ ));
131
+ }
94
132
return Column (new FuncBinary1_ColumnImpl<T, T, T>(
95
133
std::move (a), std::move (b),
96
- op_and <T>,
134
+ op_or <T>,
97
135
nrows, stype
98
136
));
99
137
}
@@ -103,7 +141,12 @@ class FExpr__and__ : public FExpr_BinaryOp {
103
141
104
142
py::oobj PyFExpr::nb__and__ (py::robj lhs, py::robj rhs) {
105
143
return PyFExpr::make (
106
- new FExpr__and__ (as_fexpr (lhs), as_fexpr (rhs)));
144
+ new FExpr__andor__<true >(as_fexpr (lhs), as_fexpr (rhs)));
145
+ }
146
+
147
+ py::oobj PyFExpr::nb__or__ (py::robj lhs, py::robj rhs) {
148
+ return PyFExpr::make (
149
+ new FExpr__andor__<false >(as_fexpr (lhs), as_fexpr (rhs)));
107
150
}
108
151
109
152
0 commit comments