@@ -68,6 +68,11 @@ inline static T op_or(T x, T y) {
68
68
return (x | y);
69
69
}
70
70
71
+ template <typename T>
72
+ inline static T op_xor (T x, T y) {
73
+ return (x ^ y);
74
+ }
75
+
71
76
template <bool AND>
72
77
class FExpr__andor__ : public FExpr_BinaryOp {
73
78
public:
@@ -110,7 +115,8 @@ class FExpr__andor__ : public FExpr_BinaryOp {
110
115
case SType::INT32: return make<int32_t , AND>(std::move (lcol), std::move (rcol), stype0);
111
116
case SType::INT64: return make<int64_t , AND>(std::move (lcol), std::move (rcol), stype0);
112
117
default :
113
- throw TypeError () << " Operator `&` cannot be applied to columns of "
118
+ char op = AND?' &' :' |' ;
119
+ throw TypeError () << " Operator " << op << " cannot be applied to columns of "
114
120
" types `" << stype1 << " ` and `" << stype2 << " `" ;
115
121
}
116
122
}
@@ -138,6 +144,50 @@ class FExpr__andor__ : public FExpr_BinaryOp {
138
144
};
139
145
140
146
147
+ class FExpr__xor__ : public FExpr_BinaryOp {
148
+ public:
149
+ using FExpr_BinaryOp::FExpr_BinaryOp;
150
+ using FExpr_BinaryOp::lhs_;
151
+ using FExpr_BinaryOp::rhs_;
152
+
153
+
154
+ std::string name () const override { return " ^" ; }
155
+ int precedence () const noexcept override { return 8 ; }
156
+
157
+
158
+ Column evaluate1 (Column&& lcol, Column&& rcol) const override {
159
+ xassert (lcol.nrows () == rcol.nrows ());
160
+ auto stype1 = lcol.stype ();
161
+ auto stype2 = rcol.stype ();
162
+ auto stype0 = common_stype (stype1, stype2);
163
+
164
+ switch (stype0) {
165
+ case SType::BOOL: return make<int8_t >(std::move (lcol), std::move (rcol), stype0);
166
+ case SType::INT8: return make<int8_t >(std::move (lcol), std::move (rcol), stype0);
167
+ case SType::INT16: return make<int16_t >(std::move (lcol), std::move (rcol), stype0);
168
+ case SType::INT32: return make<int32_t >(std::move (lcol), std::move (rcol), stype0);
169
+ case SType::INT64: return make<int64_t >(std::move (lcol), std::move (rcol), stype0);
170
+ default :
171
+ throw TypeError () << " Operator `^` cannot be applied to columns of "
172
+ " types `" << stype1 << " ` and `" << stype2 << " `" ;
173
+ }
174
+ }
175
+
176
+ private:
177
+ template <typename T>
178
+ static Column make (Column&& a, Column&& b, SType stype) {
179
+ xassert (compatible_type<T>(stype));
180
+ size_t nrows = a.nrows ();
181
+ a.cast_inplace (stype);
182
+ b.cast_inplace (stype);
183
+ return Column (new FuncBinary1_ColumnImpl<T, T, T>(
184
+ std::move (a), std::move (b),
185
+ op_xor<T>,
186
+ nrows, stype
187
+ ));
188
+ }
189
+ };
190
+
141
191
142
192
py::oobj PyFExpr::nb__and__ (py::robj lhs, py::robj rhs) {
143
193
return PyFExpr::make (
@@ -149,6 +199,13 @@ py::oobj PyFExpr::nb__or__(py::robj lhs, py::robj rhs) {
149
199
new FExpr__andor__<false >(as_fexpr (lhs), as_fexpr (rhs)));
150
200
}
151
201
202
+ py::oobj PyFExpr::nb__xor__ (py::robj lhs, py::robj rhs) {
203
+ return PyFExpr::make (
204
+ new FExpr__xor__ (as_fexpr (lhs), as_fexpr (rhs)));
205
+ }
206
+
152
207
153
208
154
209
}} // namespace dt::expr
210
+
211
+
0 commit comments