From add3684843261cc0e4c04fed8c5ea8ea97e8e805 Mon Sep 17 00:00:00 2001 From: samukweku Date: Wed, 15 Mar 2023 22:55:05 +1100 Subject: [PATCH 01/11] skeleton for uinvert --- src/core/expr/funary/uinvert.cc | 88 +++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/core/expr/funary/uinvert.cc diff --git a/src/core/expr/funary/uinvert.cc b/src/core/expr/funary/uinvert.cc new file mode 100644 index 0000000000..d76f4e7357 --- /dev/null +++ b/src/core/expr/funary/uinvert.cc @@ -0,0 +1,88 @@ +//------------------------------------------------------------------------------ +// Copyright 2023 H2O.ai +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//------------------------------------------------------------------------------ +#include "column/const.h" +#include "documentation.h" +#include "expr/fexpr_column.h" +#include "expr/funary/umaker.h" +#include "expr/eval_context.h" +#include "expr/workframe.h" +#include "python/xargs.h" +namespace dt +{ + namespace expr + { + + FExpr_UINVERT::FExpr_UINVERT(ptrExpr &&arg) : arg_(std::move(arg)) + {} + + std::string FExpr_UINVERT::repr() const + { + std::string out = "uinvert"; + out += '('; + out += arg_->repr(); + out += ')'; + return out; + } + + static Column make_isna_col(Column &&col) + { + switch (stype) { + case SType::VOID: return umaker_ptr(new umaker_copy()); + case SType::BOOL: return umaker1::make(op_invert_bool, SType::AUTO, SType::BOOL); + case SType::INT8: return _uinvert(); + case SType::INT16: return _uinvert(); + case SType::INT32: return _uinvert(); + case SType::INT64: return _uinvert(); + default: + throw TypeError() << "Cannot apply unary `operator ~` to a column with " + "stype `" << stype << "`"; + } + } + + Workframe FExpr_UINVERT::evaluate_n(EvalContext &ctx) const + { + Workframe wf = arg_->evaluate_n(ctx); + + for (size_t i = 0; i < wf.ncols(); ++i) + { + Column coli = make_isna_col(wf.retrieve_column(i)); + wf.replace_column(i, std::move(coli)); + } + + return wf; + } + + static py::oobj pyfn_isna(const py::XArgs &args) + { + auto uinvert = args[0].to_oobj(); + return PyFExpr::make(new FExpr_ISNA(as_fexpr(uinvert))); + } + + DECLARE_PYFN(&pyfn_isna) + ->name("uinvert") + ->docs(doc_math_isna) + ->arg_names({"cols"}) + ->n_positional_args(1) + ->n_required_args(1); + + } +} // dt::expr From 927ac0b1824a934c53ac08cd74fe2b266cc21c28 Mon Sep 17 00:00:00 2001 From: samukweku Date: Wed, 29 Mar 2023 22:31:55 +1100 Subject: [PATCH 02/11] uinvert fexpr --- src/core/expr/fexpr.cc | 6 +- src/core/expr/fexpr.h | 3 +- src/core/expr/funary/uinvert.cc | 121 ++++++++++++++++++-------------- src/core/expr/funary/umaker.cc | 2 +- src/core/expr/funary/umaker.h | 2 +- src/core/python/xobject.h | 13 +++- 6 files changed, 88 insertions(+), 59 deletions(-) diff --git a/src/core/expr/fexpr.cc b/src/core/expr/fexpr.cc index dfd59391cc..cc784d679f 100644 --- a/src/core/expr/fexpr.cc +++ b/src/core/expr/fexpr.cc @@ -215,9 +215,9 @@ bool PyFExpr::nb__bool__() { " f.B != 0\n"; } -oobj PyFExpr::nb__invert__() { - return make_unexpr(dt::expr::Op::UINVERT, this); -} +// oobj PyFExpr::nb__invert__() { +// return make_unexpr(dt::expr::Op::UINVERT, this); +// } oobj PyFExpr::nb__neg__() { return make_unexpr(dt::expr::Op::UMINUS, this); diff --git a/src/core/expr/fexpr.h b/src/core/expr/fexpr.h index b292bbb1d8..9d4ccc741e 100644 --- a/src/core/expr/fexpr.h +++ b/src/core/expr/fexpr.h @@ -163,6 +163,7 @@ class PyFExpr : public py::XObject { static py::oobj nb__sub__ (py::robj, py::robj); static py::oobj nb__mul__ (py::robj, py::robj); static py::oobj nb__floordiv__(py::robj, py::robj); + static py::oobj nb__invert__ (py::robj); static py::oobj nb__truediv__ (py::robj, py::robj); static py::oobj nb__mod__ (py::robj, py::robj); static py::oobj nb__pow__ (py::robj, py::robj, py::robj); @@ -172,7 +173,7 @@ class PyFExpr : public py::XObject { static py::oobj nb__lshift__ (py::robj, py::robj); static py::oobj nb__rshift__ (py::robj, py::robj); bool nb__bool__(); - py::oobj nb__invert__(); + //py::oobj nb__invert__(); py::oobj nb__neg__(); py::oobj nb__pos__(); diff --git a/src/core/expr/funary/uinvert.cc b/src/core/expr/funary/uinvert.cc index d76f4e7357..1a11348958 100644 --- a/src/core/expr/funary/uinvert.cc +++ b/src/core/expr/funary/uinvert.cc @@ -1,5 +1,5 @@ //------------------------------------------------------------------------------ -// Copyright 2023 H2O.ai +// Copyright 2022-2023 H2O.ai // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -20,69 +20,86 @@ // IN THE SOFTWARE. //------------------------------------------------------------------------------ #include "column/const.h" -#include "documentation.h" +#include "column/func_unary.h" +#include "column/isna.h" #include "expr/fexpr_column.h" -#include "expr/funary/umaker.h" +#include "documentation.h" +#include "expr/fexpr_func_unary.h" #include "expr/eval_context.h" #include "expr/workframe.h" #include "python/xargs.h" -namespace dt -{ - namespace expr - { +#include "stype.h" +namespace dt { +namespace expr { - FExpr_UINVERT::FExpr_UINVERT(ptrExpr &&arg) : arg_(std::move(arg)) - {} - std::string FExpr_UINVERT::repr() const - { - std::string out = "uinvert"; - out += '('; - out += arg_->repr(); - out += ')'; - return out; - } +class FExpr_UInvert : public FExpr_FuncUnary { + public: + using FExpr_FuncUnary::FExpr_FuncUnary; - static Column make_isna_col(Column &&col) - { - switch (stype) { - case SType::VOID: return umaker_ptr(new umaker_copy()); - case SType::BOOL: return umaker1::make(op_invert_bool, SType::AUTO, SType::BOOL); - case SType::INT8: return _uinvert(); - case SType::INT16: return _uinvert(); - case SType::INT32: return _uinvert(); - case SType::INT64: return _uinvert(); - default: - throw TypeError() << "Cannot apply unary `operator ~` to a column with " - "stype `" << stype << "`"; - } - } - Workframe FExpr_UINVERT::evaluate_n(EvalContext &ctx) const - { - Workframe wf = arg_->evaluate_n(ctx); + std::string name() const override { + return "uinvert"; + } - for (size_t i = 0; i < wf.ncols(); ++i) - { - Column coli = make_isna_col(wf.retrieve_column(i)); - wf.replace_column(i, std::move(coli)); - } + template + static inline T op_invert(T x) { + return ~x; + } - return wf; + static inline int8_t op_invert_bool(int8_t x) { + return !x; } + + Column evaluate1(Column&& col) const override{ + SType stype = col.stype(); + Column col_out; - static py::oobj pyfn_isna(const py::XArgs &args) - { - auto uinvert = args[0].to_oobj(); - return PyFExpr::make(new FExpr_ISNA(as_fexpr(uinvert))); + switch (stype) { + case SType::VOID: return Column(new ConstNa_ColumnImpl( + col.nrows(), SType::VOID + )); + case SType::BOOL: + col_out = Column(new FuncUnary1_ColumnImpl( + std::move(col), op_invert_bool, col.nrows(), SType::BOOL + )); + break; + case SType::INT8: + col_out = Column(new FuncUnary1_ColumnImpl( + std::move(col), op_invert, col.nrows(), SType::INT8 + )); + break; + case SType::INT16: + col_out = Column(new FuncUnary1_ColumnImpl( + std::move(col), op_invert, col.nrows(), SType::INT16 + )); + break; + case SType::INT32: + case SType::DATE32: + col_out = Column(new FuncUnary1_ColumnImpl( + std::move(col), op_invert, col.nrows(), SType::INT32 + )); + break; + case SType::INT64: + case SType::TIME64: + col_out = Column(new FuncUnary1_ColumnImpl( + std::move(col), op_invert, col.nrows(), SType::INT64 + )); + break;; + default: + throw TypeError() << "Cannot apply unary `operator ~` to a column with " + "stype `" << stype << "`"; + } + if (stype == SType::DATE32 || stype == SType::TIME64) { + col_out.cast_inplace(stype); + } + return col_out; } +}; - DECLARE_PYFN(&pyfn_isna) - ->name("uinvert") - ->docs(doc_math_isna) - ->arg_names({"cols"}) - ->n_positional_args(1) - ->n_required_args(1); +py::oobj PyFExpr::nb__invert__(py::robj lhs) { + return PyFExpr::make( + new FExpr_UInvert(as_fexpr(lhs))); +} - } -} // dt::expr +}} // dt::expr diff --git a/src/core/expr/funary/umaker.cc b/src/core/expr/funary/umaker.cc index 0bd9867f8e..ffd08b23ea 100644 --- a/src/core/expr/funary/umaker.cc +++ b/src/core/expr/funary/umaker.cc @@ -63,7 +63,7 @@ umaker_ptr resolve_op(Op opcode, SType stype) // Basic case Op::UPLUS: return resolve_op_uplus(stype); case Op::UMINUS: return resolve_op_uminus(stype); - case Op::UINVERT: return resolve_op_uinvert(stype); + //case Op::UINVERT: return resolve_op_uinvert(stype); // Math: trigonometric case Op::SIN: return resolve_op_sin(stype); diff --git a/src/core/expr/funary/umaker.h b/src/core/expr/funary/umaker.h index 30031729a9..651d8d4bba 100644 --- a/src/core/expr/funary/umaker.h +++ b/src/core/expr/funary/umaker.h @@ -84,7 +84,7 @@ umaker_ptr resolve_op(Op, SType); // Basic umaker_ptr resolve_op_uplus(SType); umaker_ptr resolve_op_uminus(SType); -umaker_ptr resolve_op_uinvert(SType); +//umaker_ptr resolve_op_uinvert(SType); // Trigonometric umaker_ptr resolve_op_sin(SType); diff --git a/src/core/python/xobject.h b/src/core/python/xobject.h index 22ba4f25eb..b59abffaf5 100644 --- a/src/core/python/xobject.h +++ b/src/core/python/xobject.h @@ -519,6 +519,17 @@ PyObject* _safe_unary(PyObject* self) noexcept { } } +template +PyObject* _safe_uunary(PyObject* self) noexcept { + auto cl = dt::CallLogger::unaryfn(self, OP); + try { + return METH(py::robj(self)).release(); + } catch (const std::exception& e) { + exception_to_python(e); + return nullptr; + } +} + template PyObject* _safe_binary(PyObject* self, PyObject* other) noexcept { @@ -778,7 +789,7 @@ PyObject* _safe_cmp(PyObject* x, PyObject* y, int op) noexcept { #define METHOD__INVERT__(METH) \ - py::_safe_unary, \ + py::_safe_uunary, \ py::XTypeMaker::nb_invert_tag From 11fb8b676209bb1179a29d63bf96e98c93d95f9e Mon Sep 17 00:00:00 2001 From: samukweku Date: Wed, 29 Mar 2023 22:36:30 +1100 Subject: [PATCH 03/11] formatting --- src/core/expr/funary/uinvert.cc | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/core/expr/funary/uinvert.cc b/src/core/expr/funary/uinvert.cc index 1a11348958..e708ada467 100644 --- a/src/core/expr/funary/uinvert.cc +++ b/src/core/expr/funary/uinvert.cc @@ -61,30 +61,30 @@ class FExpr_UInvert : public FExpr_FuncUnary { )); case SType::BOOL: col_out = Column(new FuncUnary1_ColumnImpl( - std::move(col), op_invert_bool, col.nrows(), SType::BOOL - )); + std::move(col), op_invert_bool, col.nrows(), SType::BOOL + )); break; case SType::INT8: col_out = Column(new FuncUnary1_ColumnImpl( - std::move(col), op_invert, col.nrows(), SType::INT8 - )); + std::move(col), op_invert, col.nrows(), SType::INT8 + )); break; case SType::INT16: col_out = Column(new FuncUnary1_ColumnImpl( - std::move(col), op_invert, col.nrows(), SType::INT16 - )); + std::move(col), op_invert, col.nrows(), SType::INT16 + )); break; case SType::INT32: case SType::DATE32: col_out = Column(new FuncUnary1_ColumnImpl( - std::move(col), op_invert, col.nrows(), SType::INT32 - )); + std::move(col), op_invert, col.nrows(), SType::INT32 + )); break; case SType::INT64: case SType::TIME64: col_out = Column(new FuncUnary1_ColumnImpl( - std::move(col), op_invert, col.nrows(), SType::INT64 - )); + std::move(col), op_invert, col.nrows(), SType::INT64 + )); break;; default: throw TypeError() << "Cannot apply unary `operator ~` to a column with " From ac90eb6c9a9b8244eb2a0185ed496c596a687684 Mon Sep 17 00:00:00 2001 From: samukweku Date: Wed, 29 Mar 2023 22:48:22 +1100 Subject: [PATCH 04/11] restrict inverse to bool and int columns --- src/core/expr/funary/uinvert.cc | 46 ++++++++++++--------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/src/core/expr/funary/uinvert.cc b/src/core/expr/funary/uinvert.cc index e708ada467..cce19e5cd2 100644 --- a/src/core/expr/funary/uinvert.cc +++ b/src/core/expr/funary/uinvert.cc @@ -56,44 +56,32 @@ class FExpr_UInvert : public FExpr_FuncUnary { Column col_out; switch (stype) { - case SType::VOID: return Column(new ConstNa_ColumnImpl( - col.nrows(), SType::VOID - )); + case SType::VOID: + return Column(new ConstNa_ColumnImpl(col.nrows(), SType::VOID)); case SType::BOOL: - col_out = Column(new FuncUnary1_ColumnImpl( - std::move(col), op_invert_bool, col.nrows(), SType::BOOL - )); - break; + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_invert_bool, col.nrows(), SType::BOOL + )); case SType::INT8: - col_out = Column(new FuncUnary1_ColumnImpl( - std::move(col), op_invert, col.nrows(), SType::INT8 - )); - break; + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_invert, col.nrows(), SType::INT8 + )); case SType::INT16: - col_out = Column(new FuncUnary1_ColumnImpl( - std::move(col), op_invert, col.nrows(), SType::INT16 - )); - break; + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_invert, col.nrows(), SType::INT16 + )); case SType::INT32: - case SType::DATE32: - col_out = Column(new FuncUnary1_ColumnImpl( - std::move(col), op_invert, col.nrows(), SType::INT32 - )); - break; + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_invert, col.nrows(), SType::INT32 + )); case SType::INT64: - case SType::TIME64: - col_out = Column(new FuncUnary1_ColumnImpl( - std::move(col), op_invert, col.nrows(), SType::INT64 - )); - break;; + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_invert, col.nrows(), SType::INT64 + )); default: throw TypeError() << "Cannot apply unary `operator ~` to a column with " "stype `" << stype << "`"; } - if (stype == SType::DATE32 || stype == SType::TIME64) { - col_out.cast_inplace(stype); - } - return col_out; } }; From 67bba444088068f689467d34abedc7dadf6d6c27 Mon Sep 17 00:00:00 2001 From: samukweku Date: Wed, 29 Mar 2023 22:50:29 +1100 Subject: [PATCH 05/11] further cleanup of invert --- src/core/expr/funary/uinvert.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/expr/funary/uinvert.cc b/src/core/expr/funary/uinvert.cc index cce19e5cd2..2d9e510f01 100644 --- a/src/core/expr/funary/uinvert.cc +++ b/src/core/expr/funary/uinvert.cc @@ -53,7 +53,6 @@ class FExpr_UInvert : public FExpr_FuncUnary { Column evaluate1(Column&& col) const override{ SType stype = col.stype(); - Column col_out; switch (stype) { case SType::VOID: From 0752240e15ec92ab52ba71dd8b74fdadeb3ebe6c Mon Sep 17 00:00:00 2001 From: samukweku Date: Thu, 30 Mar 2023 14:32:40 +1100 Subject: [PATCH 06/11] implement unary pos FExpr --- src/core/expr/fexpr.cc | 22 +-- src/core/expr/fexpr.h | 6 +- src/core/expr/funary/umaker.cc | 2 +- src/core/expr/funary/umaker.h | 2 +- .../funary/{uinvert.cc => unary_invert.cc} | 11 +- src/core/expr/funary/unary_minus.cc | 129 ++++++++++++++++++ src/core/expr/funary/unary_plus.cc | 73 ++++++++++ src/core/python/xobject.h | 6 +- 8 files changed, 228 insertions(+), 23 deletions(-) rename src/core/expr/funary/{uinvert.cc => unary_invert.cc} (93%) create mode 100644 src/core/expr/funary/unary_minus.cc create mode 100644 src/core/expr/funary/unary_plus.cc diff --git a/src/core/expr/fexpr.cc b/src/core/expr/fexpr.cc index cc784d679f..321ce97d0d 100644 --- a/src/core/expr/fexpr.cc +++ b/src/core/expr/fexpr.cc @@ -172,11 +172,11 @@ oobj PyFExpr::m__getitem__(py::robj item) { //----- Basic arithmetics ------------------------------------------------------ -static oobj make_unexpr(dt::expr::Op op, const PyObject* self) { - return robj(Expr_Type).call({ - oint(static_cast(op)), - otuple{oobj(self)}}); -} +// static oobj make_unexpr(dt::expr::Op op, const PyObject* self) { +// return robj(Expr_Type).call({ +// oint(static_cast(op)), +// otuple{oobj(self)}}); +// } static oobj make_binexpr(dt::expr::Op op, robj lhs, robj rhs) { return robj(Expr_Type).call({ @@ -219,13 +219,13 @@ bool PyFExpr::nb__bool__() { // return make_unexpr(dt::expr::Op::UINVERT, this); // } -oobj PyFExpr::nb__neg__() { - return make_unexpr(dt::expr::Op::UMINUS, this); -} +// oobj PyFExpr::nb__neg__() { +// return make_unexpr(dt::expr::Op::UMINUS, this); +// } -oobj PyFExpr::nb__pos__() { - return make_unexpr(dt::expr::Op::UPLUS, this); -} +// oobj PyFExpr::nb__pos__() { +// return make_unexpr(dt::expr::Op::UPLUS, this); +// } diff --git a/src/core/expr/fexpr.h b/src/core/expr/fexpr.h index 9d4ccc741e..8a089cd8e8 100644 --- a/src/core/expr/fexpr.h +++ b/src/core/expr/fexpr.h @@ -164,6 +164,8 @@ class PyFExpr : public py::XObject { static py::oobj nb__mul__ (py::robj, py::robj); static py::oobj nb__floordiv__(py::robj, py::robj); static py::oobj nb__invert__ (py::robj); + static py::oobj nb__neg__ (py::robj); + static py::oobj nb__pos__ (py::robj); static py::oobj nb__truediv__ (py::robj, py::robj); static py::oobj nb__mod__ (py::robj, py::robj); static py::oobj nb__pow__ (py::robj, py::robj, py::robj); @@ -174,8 +176,8 @@ class PyFExpr : public py::XObject { static py::oobj nb__rshift__ (py::robj, py::robj); bool nb__bool__(); //py::oobj nb__invert__(); - py::oobj nb__neg__(); - py::oobj nb__pos__(); + //py::oobj nb__neg__(); + //py::oobj nb__pos__(); py::oobj len(); // [DEPRECATED] py::oobj re_match(const py::XArgs&); // [DEPRECATED] diff --git a/src/core/expr/funary/umaker.cc b/src/core/expr/funary/umaker.cc index ffd08b23ea..4fdacaf50d 100644 --- a/src/core/expr/funary/umaker.cc +++ b/src/core/expr/funary/umaker.cc @@ -62,7 +62,7 @@ umaker_ptr resolve_op(Op opcode, SType stype) switch (opcode) { // Basic case Op::UPLUS: return resolve_op_uplus(stype); - case Op::UMINUS: return resolve_op_uminus(stype); + //case Op::UMINUS: return resolve_op_uminus(stype); //case Op::UINVERT: return resolve_op_uinvert(stype); // Math: trigonometric diff --git a/src/core/expr/funary/umaker.h b/src/core/expr/funary/umaker.h index 651d8d4bba..bfe166f290 100644 --- a/src/core/expr/funary/umaker.h +++ b/src/core/expr/funary/umaker.h @@ -83,7 +83,7 @@ umaker_ptr resolve_op(Op, SType); // Basic umaker_ptr resolve_op_uplus(SType); -umaker_ptr resolve_op_uminus(SType); +//umaker_ptr resolve_op_uminus(SType); //umaker_ptr resolve_op_uinvert(SType); // Trigonometric diff --git a/src/core/expr/funary/uinvert.cc b/src/core/expr/funary/unary_invert.cc similarity index 93% rename from src/core/expr/funary/uinvert.cc rename to src/core/expr/funary/unary_invert.cc index 2d9e510f01..4ee49fb811 100644 --- a/src/core/expr/funary/uinvert.cc +++ b/src/core/expr/funary/unary_invert.cc @@ -21,12 +21,8 @@ //------------------------------------------------------------------------------ #include "column/const.h" #include "column/func_unary.h" -#include "column/isna.h" #include "expr/fexpr_column.h" -#include "documentation.h" #include "expr/fexpr_func_unary.h" -#include "expr/eval_context.h" -#include "expr/workframe.h" #include "python/xargs.h" #include "stype.h" namespace dt { @@ -50,7 +46,12 @@ class FExpr_UInvert : public FExpr_FuncUnary { static inline int8_t op_invert_bool(int8_t x) { return !x; } - + /** + * Unary operator `~` acts as logical NOT on a boolean column, + * and as a bitwise inverse on integer columns. Integer promotions + * are not applied. The operator is not applicable to floating-point + * or string columns. + */ Column evaluate1(Column&& col) const override{ SType stype = col.stype(); diff --git a/src/core/expr/funary/unary_minus.cc b/src/core/expr/funary/unary_minus.cc new file mode 100644 index 0000000000..69dab35bb1 --- /dev/null +++ b/src/core/expr/funary/unary_minus.cc @@ -0,0 +1,129 @@ +//------------------------------------------------------------------------------ +// Copyright 2022-2023 H2O.ai +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//------------------------------------------------------------------------------ +#include "column/const.h" +#include "column/func_unary.h" +#include "expr/fexpr_column.h" +#include "expr/fexpr_func_unary.h" +#include "expr/eval_context.h" +#include "expr/workframe.h" +#include "expr/fexpr.h" +#include "python/xargs.h" +#include "stype.h" +#include +namespace dt { +namespace expr { + + +class FExpr_UnaryMinus : public FExpr_FuncUnary { + public: + using FExpr_FuncUnary::FExpr_FuncUnary; + + + std::string name() const override { + return "uminus"; + } + + template + static inline T op_minus(T x) { + return -x; + } + /** + * Unary operator `+` upcasts each numeric column to INT32, but + * otherwise keeps unmodified. The operator cannot be applied to + * string columns. + */ + Column evaluate1(Column&& col) const override{ + SType stype = col.stype(); + + switch (stype) { + case SType::VOID: + return Column(new ConstNa_ColumnImpl(col.nrows(), SType::VOID)); + case SType::BOOL: + case SType::INT8: + case SType::INT16: + col.cast_inplace(SType::INT32); + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_minus, col.nrows(), SType::INT32 + )); + case SType::INT32: + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_minus, col.nrows(), SType::INT32 + )); + case SType::INT64: + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_minus, col.nrows(), SType::INT64 + )); + case SType::FLOAT32: + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_minus, col.nrows(), SType::FLOAT32 + )); + case SType::FLOAT64: + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_minus, col.nrows(), SType::FLOAT64 + )); + default: + throw TypeError() << "Cannot apply unary `operator -` to a column with " + "stype `" << stype << "`"; + } + } +}; + + +// gets the count of all rows - nulls are not checked +class FExpr_UnaryMinus_Node : public FExpr_Func { + private: + ptrExpr arg_; + public: + FExpr_UnaryMinus_Node(ptrExpr &&arg) + : arg_(std::move(arg)) + {} + + std::string repr() const override { + std::string out = "uminus"; + out += '('; + out += arg_->repr(); + out += ')'; + return out; + } + + Workframe evaluate_n(EvalContext &ctx) const override { + Workframe wf(ctx); + + return wf; + } + +}; + +py::oobj PyFExpr::nb__neg__(py::robj src) { + std::cout<, \ + py::_safe_uunary, \ py::XTypeMaker::nb_negative_tag #define METHOD__POS__(METH) \ - py::_safe_unary, \ + py::_safe_uunary, \ py::XTypeMaker::nb_positive_tag @@ -789,7 +789,7 @@ PyObject* _safe_cmp(PyObject* x, PyObject* y, int op) noexcept { #define METHOD__INVERT__(METH) \ - py::_safe_uunary, \ + py::_safe_uunary, \ py::XTypeMaker::nb_invert_tag From 53aa3a3247a85336c5e62cd8f21ff56eccaadd4a Mon Sep 17 00:00:00 2001 From: samukweku Date: Thu, 30 Mar 2023 21:12:24 +1100 Subject: [PATCH 07/11] not sure how to fix the sort with negation --- src/core/expr/funary/unary_minus.cc | 34 ----------------------------- 1 file changed, 34 deletions(-) diff --git a/src/core/expr/funary/unary_minus.cc b/src/core/expr/funary/unary_minus.cc index 69dab35bb1..4a4b7608af 100644 --- a/src/core/expr/funary/unary_minus.cc +++ b/src/core/expr/funary/unary_minus.cc @@ -87,41 +87,7 @@ class FExpr_UnaryMinus : public FExpr_FuncUnary { } }; - -// gets the count of all rows - nulls are not checked -class FExpr_UnaryMinus_Node : public FExpr_Func { - private: - ptrExpr arg_; - public: - FExpr_UnaryMinus_Node(ptrExpr &&arg) - : arg_(std::move(arg)) - {} - - std::string repr() const override { - std::string out = "uminus"; - out += '('; - out += arg_->repr(); - out += ')'; - return out; - } - - Workframe evaluate_n(EvalContext &ctx) const override { - Workframe wf(ctx); - - return wf; - } - -}; - py::oobj PyFExpr::nb__neg__(py::robj src) { - std::cout< Date: Thu, 30 Mar 2023 21:44:26 +1100 Subject: [PATCH 08/11] resolve links for unary docs --- docs/api/fexpr/__invert__.rst | 2 +- docs/api/fexpr/__neg__.rst | 2 +- docs/api/fexpr/__pos__.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/fexpr/__invert__.rst b/docs/api/fexpr/__invert__.rst index 76eab0bca8..df14cd274f 100644 --- a/docs/api/fexpr/__invert__.rst +++ b/docs/api/fexpr/__invert__.rst @@ -1,6 +1,6 @@ .. xmethod:: datatable.FExpr.__invert__ - :src: src/core/expr/fexpr.cc PyFExpr::nb__invert__ + :src: src/core/expr/funary/unary_invert.cc PyFExpr::nb__invert__ __invert__(x) -- diff --git a/docs/api/fexpr/__neg__.rst b/docs/api/fexpr/__neg__.rst index 5b843f2d40..64d1f11023 100644 --- a/docs/api/fexpr/__neg__.rst +++ b/docs/api/fexpr/__neg__.rst @@ -1,6 +1,6 @@ .. xmethod:: datatable.FExpr.__neg__ - :src: src/core/expr/fexpr.cc PyFExpr::nb__neg__ + :src: src/core/expr/funary/unary_minus.cc PyFExpr::nb__neg__ __neg__(x) -- diff --git a/docs/api/fexpr/__pos__.rst b/docs/api/fexpr/__pos__.rst index 753681c68f..720c898eef 100644 --- a/docs/api/fexpr/__pos__.rst +++ b/docs/api/fexpr/__pos__.rst @@ -1,6 +1,6 @@ .. xmethod:: datatable.FExpr.__pos__ - :src: src/core/expr/fexpr.cc PyFExpr::nb__pos__ + :src: src/core/expr/funary/unary_plus.cc PyFExpr::nb__pos__ __pos__(x) -- From 6fbb51f46751968dc9b5ca3e3bad41e9c0d78b45 Mon Sep 17 00:00:00 2001 From: samukweku Date: Fri, 31 Mar 2023 13:01:55 +1100 Subject: [PATCH 09/11] clean up --- src/core/expr/fexpr.cc | 22 ---------------------- src/core/expr/fexpr.h | 3 --- src/core/expr/funary/umaker.cc | 5 ----- src/core/expr/funary/umaker.h | 5 ----- 4 files changed, 35 deletions(-) diff --git a/src/core/expr/fexpr.cc b/src/core/expr/fexpr.cc index 321ce97d0d..e975c310b4 100644 --- a/src/core/expr/fexpr.cc +++ b/src/core/expr/fexpr.cc @@ -171,13 +171,6 @@ oobj PyFExpr::m__getitem__(py::robj item) { //----- Basic arithmetics ------------------------------------------------------ - -// static oobj make_unexpr(dt::expr::Op op, const PyObject* self) { -// return robj(Expr_Type).call({ -// oint(static_cast(op)), -// otuple{oobj(self)}}); -// } - static oobj make_binexpr(dt::expr::Op op, robj lhs, robj rhs) { return robj(Expr_Type).call({ oint(static_cast(op)), @@ -215,21 +208,6 @@ bool PyFExpr::nb__bool__() { " f.B != 0\n"; } -// oobj PyFExpr::nb__invert__() { -// return make_unexpr(dt::expr::Op::UINVERT, this); -// } - -// oobj PyFExpr::nb__neg__() { -// return make_unexpr(dt::expr::Op::UMINUS, this); -// } - -// oobj PyFExpr::nb__pos__() { -// return make_unexpr(dt::expr::Op::UPLUS, this); -// } - - - - //----- Other methods ---------------------------------------------------------- oobj PyFExpr::extend(const XArgs& args) { diff --git a/src/core/expr/fexpr.h b/src/core/expr/fexpr.h index 8a089cd8e8..fd0ed2a23a 100644 --- a/src/core/expr/fexpr.h +++ b/src/core/expr/fexpr.h @@ -175,9 +175,6 @@ class PyFExpr : public py::XObject { static py::oobj nb__lshift__ (py::robj, py::robj); static py::oobj nb__rshift__ (py::robj, py::robj); bool nb__bool__(); - //py::oobj nb__invert__(); - //py::oobj nb__neg__(); - //py::oobj nb__pos__(); py::oobj len(); // [DEPRECATED] py::oobj re_match(const py::XArgs&); // [DEPRECATED] diff --git a/src/core/expr/funary/umaker.cc b/src/core/expr/funary/umaker.cc index 4fdacaf50d..15b6d45e22 100644 --- a/src/core/expr/funary/umaker.cc +++ b/src/core/expr/funary/umaker.cc @@ -60,11 +60,6 @@ static const umaker_ptr& get_umaker(Op opcode, SType stype) { umaker_ptr resolve_op(Op opcode, SType stype) { switch (opcode) { - // Basic - case Op::UPLUS: return resolve_op_uplus(stype); - //case Op::UMINUS: return resolve_op_uminus(stype); - //case Op::UINVERT: return resolve_op_uinvert(stype); - // Math: trigonometric case Op::SIN: return resolve_op_sin(stype); case Op::COS: return resolve_op_cos(stype); diff --git a/src/core/expr/funary/umaker.h b/src/core/expr/funary/umaker.h index bfe166f290..c13ae48ef2 100644 --- a/src/core/expr/funary/umaker.h +++ b/src/core/expr/funary/umaker.h @@ -81,11 +81,6 @@ using umaker_ptr = std::unique_ptr; // Main resolver, calls individual-op resolvers below umaker_ptr resolve_op(Op, SType); -// Basic -umaker_ptr resolve_op_uplus(SType); -//umaker_ptr resolve_op_uminus(SType); -//umaker_ptr resolve_op_uinvert(SType); - // Trigonometric umaker_ptr resolve_op_sin(SType); umaker_ptr resolve_op_cos(SType); From 46dbe77ba140c7e7d3944760b53e224849ea6d72 Mon Sep 17 00:00:00 2001 From: samukweku Date: Fri, 31 Mar 2023 13:10:45 +1100 Subject: [PATCH 10/11] remove irrelevant headers --- src/core/expr/funary/unary_invert.cc | 1 - src/core/expr/funary/unary_minus.cc | 5 ----- 2 files changed, 6 deletions(-) diff --git a/src/core/expr/funary/unary_invert.cc b/src/core/expr/funary/unary_invert.cc index 4ee49fb811..c616311b51 100644 --- a/src/core/expr/funary/unary_invert.cc +++ b/src/core/expr/funary/unary_invert.cc @@ -21,7 +21,6 @@ //------------------------------------------------------------------------------ #include "column/const.h" #include "column/func_unary.h" -#include "expr/fexpr_column.h" #include "expr/fexpr_func_unary.h" #include "python/xargs.h" #include "stype.h" diff --git a/src/core/expr/funary/unary_minus.cc b/src/core/expr/funary/unary_minus.cc index 4a4b7608af..5439b5ade8 100644 --- a/src/core/expr/funary/unary_minus.cc +++ b/src/core/expr/funary/unary_minus.cc @@ -21,14 +21,9 @@ //------------------------------------------------------------------------------ #include "column/const.h" #include "column/func_unary.h" -#include "expr/fexpr_column.h" #include "expr/fexpr_func_unary.h" -#include "expr/eval_context.h" -#include "expr/workframe.h" -#include "expr/fexpr.h" #include "python/xargs.h" #include "stype.h" -#include namespace dt { namespace expr { From 4109eb6c1b2fb7fe914ea59b444fa4cf217490ee Mon Sep 17 00:00:00 2001 From: samukweku Date: Sun, 16 Apr 2023 09:00:40 +1000 Subject: [PATCH 11/11] remove comments --- src/core/expr/funary/unary_minus.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/core/expr/funary/unary_minus.cc b/src/core/expr/funary/unary_minus.cc index 5439b5ade8..86c671d6cd 100644 --- a/src/core/expr/funary/unary_minus.cc +++ b/src/core/expr/funary/unary_minus.cc @@ -41,11 +41,7 @@ class FExpr_UnaryMinus : public FExpr_FuncUnary { static inline T op_minus(T x) { return -x; } - /** - * Unary operator `+` upcasts each numeric column to INT32, but - * otherwise keeps unmodified. The operator cannot be applied to - * string columns. - */ + Column evaluate1(Column&& col) const override{ SType stype = col.stype();