|
1 | 1 | //------------------------------------------------------------------------------ |
2 | | -// Copyright 2023 H2O.ai |
| 2 | +// Copyright 2022-2023 H2O.ai |
3 | 3 | // |
4 | 4 | // Permission is hereby granted, free of charge, to any person obtaining a |
5 | 5 | // copy of this software and associated documentation files (the "Software"), |
|
20 | 20 | // IN THE SOFTWARE. |
21 | 21 | //------------------------------------------------------------------------------ |
22 | 22 | #include "column/const.h" |
23 | | -#include "documentation.h" |
| 23 | +#include "column/func_unary.h" |
| 24 | +#include "column/isna.h" |
24 | 25 | #include "expr/fexpr_column.h" |
25 | | -#include "expr/funary/umaker.h" |
| 26 | +#include "documentation.h" |
| 27 | +#include "expr/fexpr_func_unary.h" |
26 | 28 | #include "expr/eval_context.h" |
27 | 29 | #include "expr/workframe.h" |
28 | 30 | #include "python/xargs.h" |
29 | | -namespace dt |
30 | | -{ |
31 | | - namespace expr |
32 | | - { |
| 31 | +#include "stype.h" |
| 32 | +namespace dt { |
| 33 | +namespace expr { |
33 | 34 |
|
34 | | - FExpr_UINVERT::FExpr_UINVERT(ptrExpr &&arg) : arg_(std::move(arg)) |
35 | | - {} |
36 | 35 |
|
37 | | - std::string FExpr_UINVERT::repr() const |
38 | | - { |
39 | | - std::string out = "uinvert"; |
40 | | - out += '('; |
41 | | - out += arg_->repr(); |
42 | | - out += ')'; |
43 | | - return out; |
44 | | - } |
| 36 | +class FExpr_UInvert : public FExpr_FuncUnary { |
| 37 | + public: |
| 38 | + using FExpr_FuncUnary::FExpr_FuncUnary; |
45 | 39 |
|
46 | | - static Column make_isna_col(Column &&col) |
47 | | - { |
48 | | - switch (stype) { |
49 | | - case SType::VOID: return umaker_ptr(new umaker_copy()); |
50 | | - case SType::BOOL: return umaker1<int8_t, int8_t>::make(op_invert_bool, SType::AUTO, SType::BOOL); |
51 | | - case SType::INT8: return _uinvert<int8_t>(); |
52 | | - case SType::INT16: return _uinvert<int16_t>(); |
53 | | - case SType::INT32: return _uinvert<int32_t>(); |
54 | | - case SType::INT64: return _uinvert<int64_t>(); |
55 | | - default: |
56 | | - throw TypeError() << "Cannot apply unary `operator ~` to a column with " |
57 | | - "stype `" << stype << "`"; |
58 | | - } |
59 | | - } |
60 | 40 |
|
61 | | - Workframe FExpr_UINVERT::evaluate_n(EvalContext &ctx) const |
62 | | - { |
63 | | - Workframe wf = arg_->evaluate_n(ctx); |
| 41 | + std::string name() const override { |
| 42 | + return "uinvert"; |
| 43 | + } |
64 | 44 |
|
65 | | - for (size_t i = 0; i < wf.ncols(); ++i) |
66 | | - { |
67 | | - Column coli = make_isna_col(wf.retrieve_column(i)); |
68 | | - wf.replace_column(i, std::move(coli)); |
69 | | - } |
| 45 | + template <typename T> |
| 46 | + static inline T op_invert(T x) { |
| 47 | + return ~x; |
| 48 | + } |
70 | 49 |
|
71 | | - return wf; |
| 50 | + static inline int8_t op_invert_bool(int8_t x) { |
| 51 | + return !x; |
72 | 52 | } |
| 53 | + |
| 54 | + Column evaluate1(Column&& col) const override{ |
| 55 | + SType stype = col.stype(); |
| 56 | + Column col_out; |
73 | 57 |
|
74 | | - static py::oobj pyfn_isna(const py::XArgs &args) |
75 | | - { |
76 | | - auto uinvert = args[0].to_oobj(); |
77 | | - return PyFExpr::make(new FExpr_ISNA(as_fexpr(uinvert))); |
| 58 | + switch (stype) { |
| 59 | + case SType::VOID: return Column(new ConstNa_ColumnImpl( |
| 60 | + col.nrows(), SType::VOID |
| 61 | + )); |
| 62 | + case SType::BOOL: |
| 63 | + col_out = Column(new FuncUnary1_ColumnImpl<int8_t, int8_t>( |
| 64 | + std::move(col), op_invert_bool, col.nrows(), SType::BOOL |
| 65 | + )); |
| 66 | + break; |
| 67 | + case SType::INT8: |
| 68 | + col_out = Column(new FuncUnary1_ColumnImpl<int8_t, int8_t>( |
| 69 | + std::move(col), op_invert<int8_t>, col.nrows(), SType::INT8 |
| 70 | + )); |
| 71 | + break; |
| 72 | + case SType::INT16: |
| 73 | + col_out = Column(new FuncUnary1_ColumnImpl<int16_t, int16_t>( |
| 74 | + std::move(col), op_invert<int16_t>, col.nrows(), SType::INT16 |
| 75 | + )); |
| 76 | + break; |
| 77 | + case SType::INT32: |
| 78 | + case SType::DATE32: |
| 79 | + col_out = Column(new FuncUnary1_ColumnImpl<int32_t, int32_t>( |
| 80 | + std::move(col), op_invert<int32_t>, col.nrows(), SType::INT32 |
| 81 | + )); |
| 82 | + break; |
| 83 | + case SType::INT64: |
| 84 | + case SType::TIME64: |
| 85 | + col_out = Column(new FuncUnary1_ColumnImpl<int64_t, int64_t>( |
| 86 | + std::move(col), op_invert<int64_t>, col.nrows(), SType::INT64 |
| 87 | + )); |
| 88 | + break;; |
| 89 | + default: |
| 90 | + throw TypeError() << "Cannot apply unary `operator ~` to a column with " |
| 91 | + "stype `" << stype << "`"; |
| 92 | + } |
| 93 | + if (stype == SType::DATE32 || stype == SType::TIME64) { |
| 94 | + col_out.cast_inplace(stype); |
| 95 | + } |
| 96 | + return col_out; |
78 | 97 | } |
| 98 | +}; |
79 | 99 |
|
80 | | - DECLARE_PYFN(&pyfn_isna) |
81 | | - ->name("uinvert") |
82 | | - ->docs(doc_math_isna) |
83 | | - ->arg_names({"cols"}) |
84 | | - ->n_positional_args(1) |
85 | | - ->n_required_args(1); |
| 100 | +py::oobj PyFExpr::nb__invert__(py::robj lhs) { |
| 101 | + return PyFExpr::make( |
| 102 | + new FExpr_UInvert(as_fexpr(lhs))); |
| 103 | +} |
86 | 104 |
|
87 | | - } |
88 | | -} // dt::expr |
| 105 | +}} // dt::expr |
0 commit comments