Skip to content

Commit 75c0124

Browse files
committed
lshift/rshift FExpr
1 parent 460bb03 commit 75c0124

File tree

7 files changed

+117
-9
lines changed

7 files changed

+117
-9
lines changed

docs/api/fexpr/__lshift__.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
.. xmethod:: datatable.FExpr.__lshift__
3-
:src: src/core/expr/fexpr.cc PyFExpr::nb__lshift__
3+
:src: src/core/expr/fbinary/bitwise_shift.cc PyFExpr::nb__lshift__
44

55
__lshift__(x, y)
66
--

docs/api/fexpr/__rshift__.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
.. xmethod:: datatable.FExpr.__rshift__
3-
:src: src/core/expr/fexpr.cc PyFExpr::nb__rshift__
3+
:src: src/core/expr/fbinary/bitwise_shift.cc PyFExpr::nb__rshift__
44

55
__rshift__(x, y)
66
--

src/core/expr/fbinary/bimaker.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ bimaker_ptr resolve_op(Op opcode, SType stype1, SType stype2) {
4848
//case Op::AND: return resolve_op_and(stype1, stype2);
4949
//case Op::OR: return resolve_op_or(stype1, stype2);
5050
//case Op::XOR: return resolve_op_xor(stype1, stype2);
51-
case Op::LSHIFT: return resolve_op_lshift(stype1, stype2);
52-
case Op::RSHIFT: return resolve_op_rshift(stype1, stype2);
51+
// case Op::LSHIFT: return resolve_op_lshift(stype1, stype2);
52+
// case Op::RSHIFT: return resolve_op_rshift(stype1, stype2);
5353

5454
case Op::ARCTAN2: return resolve_fn_atan2(stype1, stype2);
5555
case Op::HYPOT: return resolve_fn_hypot(stype1, stype2);

src/core/expr/fbinary/bimaker.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ bimaker_ptr resolve_op(Op, SType, SType);
8080
//bimaker_ptr resolve_op_and(SType, SType);
8181
//bimaker_ptr resolve_op_or(SType, SType);
8282
//bimaker_ptr resolve_op_xor(SType, SType);
83-
bimaker_ptr resolve_op_lshift(SType, SType);
84-
bimaker_ptr resolve_op_rshift(SType, SType);
83+
// bimaker_ptr resolve_op_lshift(SType, SType);
84+
// bimaker_ptr resolve_op_rshift(SType, SType);
8585

8686
bimaker_ptr resolve_fn_atan2(SType, SType);
8787
bimaker_ptr resolve_fn_hypot(SType, SType);

src/core/expr/fbinary/bitwise_and_or.cc renamed to src/core/expr/fbinary/bitwise_and_or_xor.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class FExpr__andor__ : public FExpr_BinaryOp {
8282

8383

8484
std::string name() const override { return AND?"&":"|"; }
85-
int precedence() const noexcept override { return AND?4:3; }
85+
int precedence() const noexcept override { return AND?9:7; }
8686

8787

8888
Column evaluate1(Column&& lcol, Column&& rcol) const override {
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//------------------------------------------------------------------------------
2+
// Copyright 2020 H2O.ai
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a
5+
// copy of this software and associated documentation files (the "Software"),
6+
// to deal in the Software without restriction, including without limitation
7+
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+
// and/or sell copies of the Software, and to permit persons to whom the
9+
// Software is furnished to do so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in
12+
// all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20+
// IN THE SOFTWARE.
21+
//------------------------------------------------------------------------------
22+
#include "column/func_binary.h"
23+
#include "expr/fbinary/fexpr_binaryop.h"
24+
25+
namespace dt {
26+
namespace expr {
27+
28+
template <typename T>
29+
inline static T op_lshift(T x, int32_t y) {
30+
return (y >= 0)? static_cast<T>(x << y) : static_cast<T>(x >> -y);
31+
}
32+
33+
template <typename T>
34+
inline static T op_rshift(T x, int32_t y) {
35+
return (y >= 0)? static_cast<T>(x >> y) : static_cast<T>(x << -y);
36+
}
37+
38+
39+
template<bool LSHIFT>
40+
class FExprBitShift : public FExpr_BinaryOp {
41+
public:
42+
using FExpr_BinaryOp::FExpr_BinaryOp;
43+
using FExpr_BinaryOp::lhs_;
44+
using FExpr_BinaryOp::rhs_;
45+
46+
47+
std::string name() const override { return LSHIFT?"<<":">>"; }
48+
int precedence() const noexcept override { return 10; }
49+
50+
51+
Column evaluate1(Column&& lcol, Column&& rcol) const override {
52+
xassert(lcol.nrows() == rcol.nrows());
53+
auto stype1 = lcol.stype();
54+
auto stype2 = rcol.stype();
55+
xassert(Type::from_stype(stype1).is_integer());
56+
xassert(Type::from_stype(stype1).is_integer() || Type::from_stype(stype1).is_boolean());
57+
58+
auto stype0 = (stype2 == SType::INT32)? SType::AUTO : SType::INT32;
59+
60+
switch (stype1) {
61+
case SType::INT8: return make<int8_t, LSHIFT>(std::move(lcol), std::move(rcol), stype0);
62+
case SType::INT16: return make<int16_t, LSHIFT>(std::move(lcol), std::move(rcol), stype0);
63+
case SType::INT32: return make<int32_t, LSHIFT>(std::move(lcol), std::move(rcol), stype0);
64+
case SType::INT64: return make<int64_t, LSHIFT>(std::move(lcol), std::move(rcol), stype0);
65+
default:
66+
std::string op = LSHIFT?"<<":">>";
67+
throw TypeError() << "Operator " << op << " cannot be applied to columns of "
68+
"types `" << stype1 << "` and `" << stype2 << "`";
69+
}
70+
}
71+
72+
private:
73+
template <typename T, bool L_SHIFT>
74+
static Column make(Column&& a, Column&& b, SType stype) {
75+
xassert(compatible_type<T>(stype));
76+
size_t nrows = a.nrows();
77+
b.cast_inplace(stype);
78+
if (L_SHIFT) {
79+
return Column(new FuncBinary1_ColumnImpl<T, int32_t, T>(
80+
std::move(a), std::move(b),
81+
op_lshift<T>,
82+
nrows, a.stype()
83+
));
84+
}
85+
return Column(new FuncBinary1_ColumnImpl<T, int32_t, T>(
86+
std::move(a), std::move(b),
87+
op_rshift<T>,
88+
nrows, a.stype()
89+
));
90+
}
91+
};
92+
93+
94+
py::oobj PyFExpr::nb__lshift__(py::robj lhs, py::robj rhs) {
95+
return PyFExpr::make(
96+
new FExprBitShift<true>(as_fexpr(lhs), as_fexpr(rhs)));
97+
}
98+
99+
py::oobj PyFExpr::nb__rshift__(py::robj lhs, py::robj rhs) {
100+
return PyFExpr::make(
101+
new FExprBitShift<false>(as_fexpr(lhs), as_fexpr(rhs)));
102+
}
103+
104+
}} // namespace dt::expr
105+
106+
107+
108+

src/core/expr/fexpr.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,8 @@ static oobj make_binexpr(dt::expr::Op op, robj lhs, robj rhs) {
188188
//oobj PyFExpr::nb__and__(robj lhs, robj rhs) { return make_binexpr(dt::expr::Op::AND, lhs, rhs); }
189189
//oobj PyFExpr::nb__xor__(robj lhs, robj rhs) { return make_binexpr(dt::expr::Op::XOR, lhs, rhs); }
190190
//oobj PyFExpr::nb__or__(robj lhs, robj rhs) { return make_binexpr(dt::expr::Op::OR, lhs, rhs); }
191-
oobj PyFExpr::nb__lshift__(robj lhs, robj rhs) { return make_binexpr(dt::expr::Op::LSHIFT, lhs, rhs); }
192-
oobj PyFExpr::nb__rshift__(robj lhs, robj rhs) { return make_binexpr(dt::expr::Op::RSHIFT, lhs, rhs); }
191+
//oobj PyFExpr::nb__lshift__(robj lhs, robj rhs) { return make_binexpr(dt::expr::Op::LSHIFT, lhs, rhs); }
192+
//oobj PyFExpr::nb__rshift__(robj lhs, robj rhs) { return make_binexpr(dt::expr::Op::RSHIFT, lhs, rhs); }
193193

194194
bool PyFExpr::nb__bool__() {
195195
throw TypeError() <<

0 commit comments

Comments
 (0)