From 911ca8fc899029849fa1c53b9855db59be0cd0fd Mon Sep 17 00:00:00 2001 From: samukweku Date: Sun, 2 Apr 2023 23:24:17 +1000 Subject: [PATCH 1/8] fexpr for hyperbolic functions --- docs/api/math/arcosh.rst | 2 +- docs/api/math/arsinh.rst | 2 +- docs/api/math/artanh.rst | 2 +- docs/api/math/cosh.rst | 2 +- docs/api/math/sinh.rst | 2 +- docs/api/math/tanh.rst | 2 +- src/core/expr/funary/fexpr_hyperbolic.cc | 236 +++++++++++++++++++++++ src/core/expr/funary/hyperbolic.cc | 149 -------------- src/core/expr/funary/pyfn.cc | 8 - src/core/expr/funary/pyfn.h | 8 - src/core/expr/funary/umaker.cc | 8 - src/core/expr/funary/umaker.h | 7 - src/core/expr/op.h | 8 - 13 files changed, 242 insertions(+), 194 deletions(-) create mode 100644 src/core/expr/funary/fexpr_hyperbolic.cc delete mode 100644 src/core/expr/funary/hyperbolic.cc diff --git a/docs/api/math/arcosh.rst b/docs/api/math/arcosh.rst index 99dcd786fe..b656e009f9 100644 --- a/docs/api/math/arcosh.rst +++ b/docs/api/math/arcosh.rst @@ -1,6 +1,6 @@ .. xfunction:: datatable.math.arcosh - :src: src/core/expr/funary/hyperbolic.cc resolve_op_arcosh + :src: src/core/expr/funary/fexpr_hyperbolic.cc pyfn_arcosh :cvar: doc_math_arcosh :signature: arcosh(x) diff --git a/docs/api/math/arsinh.rst b/docs/api/math/arsinh.rst index 5200b3f963..dc28cda0ce 100644 --- a/docs/api/math/arsinh.rst +++ b/docs/api/math/arsinh.rst @@ -1,6 +1,6 @@ .. xfunction:: datatable.math.arsinh - :src: src/core/expr/funary/hyperbolic.cc resolve_op_arsinh + :src: src/core/expr/funary/fexpr_hyperbolic.cc pyfn_arsinh :cvar: doc_math_arsinh :signature: arsinh(x) diff --git a/docs/api/math/artanh.rst b/docs/api/math/artanh.rst index a5ae09d214..3826d6557c 100644 --- a/docs/api/math/artanh.rst +++ b/docs/api/math/artanh.rst @@ -1,6 +1,6 @@ .. xfunction:: datatable.math.artanh - :src: src/core/expr/funary/hyperbolic.cc resolve_op_artanh + :src: src/core/expr/funary/fexpr_hyperbolic.cc pyfn_artanh :cvar: doc_math_artanh :signature: artanh(x) diff --git a/docs/api/math/cosh.rst b/docs/api/math/cosh.rst index 1db6cc49b5..cf26f61133 100644 --- a/docs/api/math/cosh.rst +++ b/docs/api/math/cosh.rst @@ -1,6 +1,6 @@ .. xfunction:: datatable.math.cosh - :src: src/core/expr/funary/hyperbolic.cc resolve_op_cosh + :src: src/core/expr/funary/fexpr_hyperbolic.cc pyfn_cosh :cvar: doc_math_cosh :signature: cosh(x) diff --git a/docs/api/math/sinh.rst b/docs/api/math/sinh.rst index 76380baf82..e1875fcd52 100644 --- a/docs/api/math/sinh.rst +++ b/docs/api/math/sinh.rst @@ -1,6 +1,6 @@ .. xfunction:: datatable.math.sinh - :src: src/core/expr/funary/hyperbolic.cc resolve_op_sinh + :src: src/core/expr/funary/fexpr_hyperbolic.cc pyfn_sinh :cvar: doc_math_sinh :signature: sinh(x) diff --git a/docs/api/math/tanh.rst b/docs/api/math/tanh.rst index b0e9a6c86a..6faf1e4138 100644 --- a/docs/api/math/tanh.rst +++ b/docs/api/math/tanh.rst @@ -1,6 +1,6 @@ .. xfunction:: datatable.math.tanh - :src: src/core/expr/funary/hyperbolic.cc resolve_op_tanh + :src: src/core/expr/funary/fexpr_hyperbolic.cc pyfn_tanh :cvar: doc_math_tanh :signature: tanh(x) diff --git a/src/core/expr/funary/fexpr_hyperbolic.cc b/src/core/expr/funary/fexpr_hyperbolic.cc new file mode 100644 index 0000000000..e25d7622cf --- /dev/null +++ b/src/core/expr/funary/fexpr_hyperbolic.cc @@ -0,0 +1,236 @@ +//------------------------------------------------------------------------------ +// 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 +#include "column/const.h" +#include "column/func_unary.h" +#include "documentation.h" +#include "expr/fexpr_func_unary.h" +#include "python/xargs.h" +#include "stype.h" +namespace dt { +namespace expr { + +template +class FExpr_Hyperbolic : public FExpr_FuncUnary { + public: + using FExpr_FuncUnary::FExpr_FuncUnary; + + static std::string function_name() { + switch (POS) { + case 1: + return "sinh"; + case 2: + return "cosh"; + case 3: + return "tanh"; + case 4: + return "arsinh"; + case 5: + return "arcosh"; + case 6: + return "artanh"; + } + + } + + + std::string name() const override { + return function_name(); + } + + /** + * All standard hyperbolic functions have the same signature: + * + * VOID -> VOID + * {BOOL, INT*, FLOAT64} -> FLOAT64 + * FLOAT32 -> FLOAT32 + * + */ + template + static inline T op_sinh(T x) { + return sinh(x); + } + + template + static inline T op_cosh(T x) { + return cosh(x); + } + + template + static inline T op_tanh(T x) { + return tanh(x); + } + + template + static inline T op_arsinh(T x) { + return asinh(x); + } + + template + static inline T op_arcosh(T x) { + return acosh(x); + } + + template + static inline T op_artanh(T x) { + return atanh(x); + } + + 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: + case SType::INT32: + case SType::INT64: + col.cast_inplace(SType::FLOAT64); + return make(std::move(col)); + case SType::FLOAT32: + return make(std::move(col)); + case SType::FLOAT64: + return make(std::move(col)); + default: + std::string func_name = function_name(); + throw TypeError() << "Function `" << func_name << "` cannot be applied to a " + "column of type `" << stype << "`"; + } + } + + private: + template + static Column make(Column&& col) { + xassert(compatible_type(col.stype())); + switch (POSS) { + case 1: + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_sinh, + col.nrows(), col.stype() + )); + case 2: + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_cosh, + col.nrows(), col.stype() + )); + case 3: + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_tanh, + col.nrows(), col.stype() + )); + case 4: + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_arsinh, + col.nrows(), col.stype() + )); + case 5: + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_arcosh, + col.nrows(), col.stype() + )); + case 6: + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_artanh, + col.nrows(), col.stype() + )); + } + + } + +}; + +static py::oobj pyfn_sinh(const py::XArgs &args) { + auto arg = args[0].to_oobj(); + return PyFExpr::make(new FExpr_Hyperbolic<1>(as_fexpr(arg))); +} + +static py::oobj pyfn_cosh(const py::XArgs &args) { + auto arg = args[0].to_oobj(); + return PyFExpr::make(new FExpr_Hyperbolic<2>(as_fexpr(arg))); +} + +static py::oobj pyfn_tanh(const py::XArgs &args) { + auto arg = args[0].to_oobj(); + return PyFExpr::make(new FExpr_Hyperbolic<3>(as_fexpr(arg))); +} + +static py::oobj pyfn_arsinh(const py::XArgs &args) { + auto arg = args[0].to_oobj(); + return PyFExpr::make(new FExpr_Hyperbolic<4>(as_fexpr(arg))); +} + +static py::oobj pyfn_arcosh(const py::XArgs &args) { + auto arg = args[0].to_oobj(); + return PyFExpr::make(new FExpr_Hyperbolic<5>(as_fexpr(arg))); +} + +static py::oobj pyfn_artanh(const py::XArgs &args) { + auto arg = args[0].to_oobj(); + return PyFExpr::make(new FExpr_Hyperbolic<6>(as_fexpr(arg))); +} + + +DECLARE_PYFN(&pyfn_sinh) + ->name("sinh") + ->docs(doc_math_sinh) + ->arg_names({"cols"}) + ->n_positional_args(1) + ->n_required_args(1); + +DECLARE_PYFN(&pyfn_cosh) + ->name("cosh") + ->docs(doc_math_cosh) + ->arg_names({"cols"}) + ->n_positional_args(1) + ->n_required_args(1); + +DECLARE_PYFN(&pyfn_tanh) + ->name("tanh") + ->docs(doc_math_tanh) + ->arg_names({"cols"}) + ->n_positional_args(1) + ->n_required_args(1); + +DECLARE_PYFN(&pyfn_arsinh) + ->name("arsinh") + ->docs(doc_math_arsinh) + ->arg_names({"cols"}) + ->n_positional_args(1) + ->n_required_args(1); + +DECLARE_PYFN(&pyfn_arcosh) + ->name("arcosh") + ->docs(doc_math_arcosh) + ->arg_names({"cols"}) + ->n_positional_args(1) + ->n_required_args(1); + +DECLARE_PYFN(&pyfn_artanh) + ->name("artanh") + ->docs(doc_math_artanh) + ->arg_names({"cols"}) + ->n_positional_args(1) + ->n_required_args(1); + +}} // dt::expr \ No newline at end of file diff --git a/src/core/expr/funary/hyperbolic.cc b/src/core/expr/funary/hyperbolic.cc deleted file mode 100644 index 3d6f671c12..0000000000 --- a/src/core/expr/funary/hyperbolic.cc +++ /dev/null @@ -1,149 +0,0 @@ -//------------------------------------------------------------------------------ -// Copyright 2019-2020 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 -#include "documentation.h" -#include "expr/funary/pyfn.h" -#include "expr/funary/umaker.h" -#include "expr/funary/umaker_impl.h" -#include "ltype.h" -namespace dt { -namespace expr { - - -using func32_t = float(*)(float); -using func64_t = double(*)(double); - -/** - * All standard hyperbolic functions have the same signature: - * - * VOID -> VOID - * {BOOL, INT*, FLOAT64} -> FLOAT64 - * FLOAT32 -> FLOAT32 - * - */ -static umaker_ptr _resolve_hyp(SType stype, const char* name, - func32_t fn32, func64_t fn64) -{ - if (stype == SType::VOID) { - return umaker_ptr(new umaker_copy()); - } - if (stype == SType::FLOAT64) { - return umaker1::make(fn64, SType::AUTO, SType::FLOAT64); - } - if (stype == SType::FLOAT32) { - return umaker1::make(fn32, SType::AUTO, SType::FLOAT32); - } - if (stype == SType::BOOL || stype_to_ltype(stype) == LType::INT) { - return umaker1::make(fn64, SType::FLOAT64, SType::FLOAT64); - } - throw TypeError() << "Function `" << name << "` cannot be applied to a " - "column of type `" << stype << "`"; -} - - - - -//------------------------------------------------------------------------------ -// Op::SINH -//------------------------------------------------------------------------------ - -py::PKArgs args_sinh(1, 0, 0, false, false, {"x"}, "sinh", dt::doc_math_sinh); - - -umaker_ptr resolve_op_sinh(SType stype) { - return _resolve_hyp(stype, "sinh", &std::sinh, &std::sinh); -} - - - - -//------------------------------------------------------------------------------ -// Op::COSH -//------------------------------------------------------------------------------ - -py::PKArgs args_cosh(1, 0, 0, false, false, {"x"}, "cosh", dt::doc_math_cosh); - - -umaker_ptr resolve_op_cosh(SType stype) { - return _resolve_hyp(stype, "cosh", &std::cosh, &std::cosh); -} - - - - -//------------------------------------------------------------------------------ -// Op::TANH -//------------------------------------------------------------------------------ - -py::PKArgs args_tanh(1, 0, 0, false, false, {"x"}, "tanh", dt::doc_math_tanh); - - -umaker_ptr resolve_op_tanh(SType stype) { - return _resolve_hyp(stype, "tanh", &std::tanh, &std::tanh); -} - - - - -//------------------------------------------------------------------------------ -// Op::ARSINH -//------------------------------------------------------------------------------ - -py::PKArgs args_arsinh(1, 0, 0, false, false, {"x"}, "arsinh", dt::doc_math_arsinh); - - -umaker_ptr resolve_op_arsinh(SType stype) { - return _resolve_hyp(stype, "arsinh", &std::asinh, &std::asinh); -} - - - - -//------------------------------------------------------------------------------ -// Op::ARCOSH -//------------------------------------------------------------------------------ - -py::PKArgs args_arcosh(1, 0, 0, false, false, {"x"}, "arcosh", dt::doc_math_arcosh); - - -umaker_ptr resolve_op_arcosh(SType stype) { - return _resolve_hyp(stype, "arcosh", &std::acosh, &std::acosh); -} - - - - -//------------------------------------------------------------------------------ -// Op::ARTANH -//------------------------------------------------------------------------------ - -py::PKArgs args_artanh(1, 0, 0, false, false, {"x"}, "artanh", dt::doc_math_artanh); - - -umaker_ptr resolve_op_artanh(SType stype) { - return _resolve_hyp(stype, "artanh", &std::atanh, &std::atanh); -} - - - - -}} // namespace dt::expr diff --git a/src/core/expr/funary/pyfn.cc b/src/core/expr/funary/pyfn.cc index 844cd03bea..ac12460029 100644 --- a/src/core/expr/funary/pyfn.cc +++ b/src/core/expr/funary/pyfn.cc @@ -121,14 +121,6 @@ void py::DatatableModule::init_funary() FUNARY(args_deg2rad, Op::DEG2RAD); FUNARY(args_rad2deg, Op::RAD2DEG); - // Hyperbolic - FUNARY(args_sinh, Op::SINH); - FUNARY(args_cosh, Op::COSH); - FUNARY(args_tanh, Op::TANH); - FUNARY(args_arsinh, Op::ARSINH); - FUNARY(args_arcosh, Op::ARCOSH); - FUNARY(args_artanh, Op::ARTANH); - // Exponential/power FUNARY(args_cbrt, Op::CBRT); FUNARY(args_exp, Op::EXP); diff --git a/src/core/expr/funary/pyfn.h b/src/core/expr/funary/pyfn.h index 274be5690a..64b43a85a8 100644 --- a/src/core/expr/funary/pyfn.h +++ b/src/core/expr/funary/pyfn.h @@ -36,14 +36,6 @@ extern py::PKArgs args_arctan; extern py::PKArgs args_deg2rad; extern py::PKArgs args_rad2deg; -// Hyperbolic -extern py::PKArgs args_sinh; -extern py::PKArgs args_cosh; -extern py::PKArgs args_tanh; -extern py::PKArgs args_arsinh; -extern py::PKArgs args_arcosh; -extern py::PKArgs args_artanh; - // Exponential/power extern py::PKArgs args_cbrt; extern py::PKArgs args_exp; diff --git a/src/core/expr/funary/umaker.cc b/src/core/expr/funary/umaker.cc index 0bd9867f8e..f19309cfba 100644 --- a/src/core/expr/funary/umaker.cc +++ b/src/core/expr/funary/umaker.cc @@ -75,14 +75,6 @@ umaker_ptr resolve_op(Op opcode, SType stype) case Op::DEG2RAD: return resolve_op_deg2rad(stype); case Op::RAD2DEG: return resolve_op_rad2deg(stype); - // Math: hyperbolic - case Op::SINH: return resolve_op_sinh(stype); - case Op::COSH: return resolve_op_cosh(stype); - case Op::TANH: return resolve_op_tanh(stype); - case Op::ARSINH: return resolve_op_arsinh(stype); - case Op::ARCOSH: return resolve_op_arcosh(stype); - case Op::ARTANH: return resolve_op_artanh(stype); - // Math: exponential/power case Op::CBRT: return resolve_op_cbrt(stype); case Op::EXP: return resolve_op_exp(stype); diff --git a/src/core/expr/funary/umaker.h b/src/core/expr/funary/umaker.h index 30031729a9..c17ce3b9fd 100644 --- a/src/core/expr/funary/umaker.h +++ b/src/core/expr/funary/umaker.h @@ -96,13 +96,6 @@ umaker_ptr resolve_op_arctan(SType); umaker_ptr resolve_op_deg2rad(SType); umaker_ptr resolve_op_rad2deg(SType); -// Hyperbolic -umaker_ptr resolve_op_sinh(SType); -umaker_ptr resolve_op_cosh(SType); -umaker_ptr resolve_op_tanh(SType); -umaker_ptr resolve_op_arsinh(SType); -umaker_ptr resolve_op_arcosh(SType); -umaker_ptr resolve_op_artanh(SType); // Exponential/power umaker_ptr resolve_op_cbrt(SType); diff --git a/src/core/expr/op.h b/src/core/expr/op.h index 6ca51b8f29..9b8fa8fcc0 100644 --- a/src/core/expr/op.h +++ b/src/core/expr/op.h @@ -91,14 +91,6 @@ enum class Op : size_t { DEG2RAD, // funary/trigonometric.cc RAD2DEG, // funary/trigonometric.cc - // Math: hyperbolic - SINH, // funary/hyperbolic.cc - COSH, // funary/hyperbolic.cc - TANH, // funary/hyperbolic.cc - ARSINH, // funary/hyperbolic.cc - ARCOSH, // funary/hyperbolic.cc - ARTANH, // funary/hyperbolic.cc - // Math: exponential/power CBRT, // funary/exponential.cc EXP, // funary/exponential.cc From 6edde572aed0f377a0df6d6292ad71015c90e96f Mon Sep 17 00:00:00 2001 From: samukweku Date: Sun, 2 Apr 2023 23:29:51 +1000 Subject: [PATCH 2/8] update links and file names --- docs/api/math/arcosh.rst | 2 +- docs/api/math/arsinh.rst | 2 +- docs/api/math/artanh.rst | 2 +- docs/api/math/cosh.rst | 2 +- docs/api/math/sinh.rst | 2 +- docs/api/math/tanh.rst | 2 +- src/core/expr/funary/{fexpr_hyperbolic.cc => hyperbolic.cc} | 0 7 files changed, 6 insertions(+), 6 deletions(-) rename src/core/expr/funary/{fexpr_hyperbolic.cc => hyperbolic.cc} (100%) diff --git a/docs/api/math/arcosh.rst b/docs/api/math/arcosh.rst index b656e009f9..856060232d 100644 --- a/docs/api/math/arcosh.rst +++ b/docs/api/math/arcosh.rst @@ -1,6 +1,6 @@ .. xfunction:: datatable.math.arcosh - :src: src/core/expr/funary/fexpr_hyperbolic.cc pyfn_arcosh + :src: src/core/expr/funary/hyperbolic.cc pyfn_arcosh :cvar: doc_math_arcosh :signature: arcosh(x) diff --git a/docs/api/math/arsinh.rst b/docs/api/math/arsinh.rst index dc28cda0ce..4ff61d3f36 100644 --- a/docs/api/math/arsinh.rst +++ b/docs/api/math/arsinh.rst @@ -1,6 +1,6 @@ .. xfunction:: datatable.math.arsinh - :src: src/core/expr/funary/fexpr_hyperbolic.cc pyfn_arsinh + :src: src/core/expr/funary/hyperbolic.cc pyfn_arsinh :cvar: doc_math_arsinh :signature: arsinh(x) diff --git a/docs/api/math/artanh.rst b/docs/api/math/artanh.rst index 3826d6557c..dd68b7765f 100644 --- a/docs/api/math/artanh.rst +++ b/docs/api/math/artanh.rst @@ -1,6 +1,6 @@ .. xfunction:: datatable.math.artanh - :src: src/core/expr/funary/fexpr_hyperbolic.cc pyfn_artanh + :src: src/core/expr/funary/hyperbolic.cc pyfn_artanh :cvar: doc_math_artanh :signature: artanh(x) diff --git a/docs/api/math/cosh.rst b/docs/api/math/cosh.rst index cf26f61133..1c490ca64a 100644 --- a/docs/api/math/cosh.rst +++ b/docs/api/math/cosh.rst @@ -1,6 +1,6 @@ .. xfunction:: datatable.math.cosh - :src: src/core/expr/funary/fexpr_hyperbolic.cc pyfn_cosh + :src: src/core/expr/funary/hyperbolic.cc pyfn_cosh :cvar: doc_math_cosh :signature: cosh(x) diff --git a/docs/api/math/sinh.rst b/docs/api/math/sinh.rst index e1875fcd52..e3f2e39534 100644 --- a/docs/api/math/sinh.rst +++ b/docs/api/math/sinh.rst @@ -1,6 +1,6 @@ .. xfunction:: datatable.math.sinh - :src: src/core/expr/funary/fexpr_hyperbolic.cc pyfn_sinh + :src: src/core/expr/funary/hyperbolic.cc pyfn_sinh :cvar: doc_math_sinh :signature: sinh(x) diff --git a/docs/api/math/tanh.rst b/docs/api/math/tanh.rst index 6faf1e4138..57c0d6e46e 100644 --- a/docs/api/math/tanh.rst +++ b/docs/api/math/tanh.rst @@ -1,6 +1,6 @@ .. xfunction:: datatable.math.tanh - :src: src/core/expr/funary/fexpr_hyperbolic.cc pyfn_tanh + :src: src/core/expr/funary/hyperbolic.cc pyfn_tanh :cvar: doc_math_tanh :signature: tanh(x) diff --git a/src/core/expr/funary/fexpr_hyperbolic.cc b/src/core/expr/funary/hyperbolic.cc similarity index 100% rename from src/core/expr/funary/fexpr_hyperbolic.cc rename to src/core/expr/funary/hyperbolic.cc From fd4a01fd431cbe9ea163a6b3f0cc380ce94bff26 Mon Sep 17 00:00:00 2001 From: samukweku Date: Sun, 2 Apr 2023 23:43:49 +1000 Subject: [PATCH 3/8] simplify logic for function selection --- src/core/expr/funary/hyperbolic.cc | 78 ++++++++---------------------- 1 file changed, 19 insertions(+), 59 deletions(-) diff --git a/src/core/expr/funary/hyperbolic.cc b/src/core/expr/funary/hyperbolic.cc index e25d7622cf..99713bfdea 100644 --- a/src/core/expr/funary/hyperbolic.cc +++ b/src/core/expr/funary/hyperbolic.cc @@ -66,34 +66,23 @@ class FExpr_Hyperbolic : public FExpr_FuncUnary { * */ template - static inline T op_sinh(T x) { - return sinh(x); - } - - template - static inline T op_cosh(T x) { - return cosh(x); - } - - template - static inline T op_tanh(T x) { - return tanh(x); - } - - template - static inline T op_arsinh(T x) { - return asinh(x); - } - - template - static inline T op_arcosh(T x) { - return acosh(x); + static inline T op_hyperbolic(T x) { + switch (POS) { + case 1: + return sinh(x); + case 2: + return cosh(x); + case 3: + return tanh(x); + case 4: + return asinh(x); + case 5: + return acosh(x); + case 6: + return atanh(x); + } } - template - static inline T op_artanh(T x) { - return atanh(x); - } Column evaluate1(Column&& col) const override{ SType stype = col.stype(); @@ -123,39 +112,10 @@ class FExpr_Hyperbolic : public FExpr_FuncUnary { template static Column make(Column&& col) { xassert(compatible_type(col.stype())); - switch (POSS) { - case 1: - return Column(new FuncUnary1_ColumnImpl( - std::move(col), op_sinh, - col.nrows(), col.stype() - )); - case 2: - return Column(new FuncUnary1_ColumnImpl( - std::move(col), op_cosh, - col.nrows(), col.stype() - )); - case 3: - return Column(new FuncUnary1_ColumnImpl( - std::move(col), op_tanh, - col.nrows(), col.stype() - )); - case 4: - return Column(new FuncUnary1_ColumnImpl( - std::move(col), op_arsinh, - col.nrows(), col.stype() - )); - case 5: - return Column(new FuncUnary1_ColumnImpl( - std::move(col), op_arcosh, - col.nrows(), col.stype() - )); - case 6: - return Column(new FuncUnary1_ColumnImpl( - std::move(col), op_artanh, - col.nrows(), col.stype() - )); - } - + return Column(new FuncUnary1_ColumnImpl( + std::move(col), op_hyperbolic, + col.nrows(), col.stype() + )); } }; From ea3205c363293f4ca888aabc8d1d8e46403fdee3 Mon Sep 17 00:00:00 2001 From: samukweku Date: Mon, 3 Apr 2023 00:41:11 +1000 Subject: [PATCH 4/8] make op_hyperbolic function a bit clearer in implementation --- src/core/expr/funary/hyperbolic.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/expr/funary/hyperbolic.cc b/src/core/expr/funary/hyperbolic.cc index 99713bfdea..489ec4a94d 100644 --- a/src/core/expr/funary/hyperbolic.cc +++ b/src/core/expr/funary/hyperbolic.cc @@ -65,9 +65,9 @@ class FExpr_Hyperbolic : public FExpr_FuncUnary { * FLOAT32 -> FLOAT32 * */ - template + template static inline T op_hyperbolic(T x) { - switch (POS) { + switch (POSN) { case 1: return sinh(x); case 2: @@ -113,7 +113,7 @@ class FExpr_Hyperbolic : public FExpr_FuncUnary { static Column make(Column&& col) { xassert(compatible_type(col.stype())); return Column(new FuncUnary1_ColumnImpl( - std::move(col), op_hyperbolic, + std::move(col), op_hyperbolic, col.nrows(), col.stype() )); } From 5246a41bdb4f180e39e773b834492ba404c41ba2 Mon Sep 17 00:00:00 2001 From: samukweku Date: Mon, 3 Apr 2023 20:36:41 +1000 Subject: [PATCH 5/8] add tests for hyperbolic functions --- tests/ijby/test-func-unary.py | 56 ++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/tests/ijby/test-func-unary.py b/tests/ijby/test-func-unary.py index 5ca952e80a..a85fd14c97 100644 --- a/tests/ijby/test-func-unary.py +++ b/tests/ijby/test-func-unary.py @@ -25,9 +25,10 @@ import pytest import random import datatable as dt -from datatable import f, g, stype, join +from datatable import dt, f, g, stype, join from datatable.internal import frame_integrity_check from tests import assert_equals +from itertools import product, islice # Sets of tuples containing test columns of each type @@ -220,3 +221,56 @@ def test_log_srcs(src, fn): mathlog(x) for x in src] assert DT1.to_list()[0] == pyans + + +#------------------------------------------------------------------------------- +# Unary hyperbolic +#------------------------------------------------------------------------------- + +def hyperbolic_func(func, t): + if t is None: return None + return func(t) + + +funcs = [math.sinh, math.cosh, math.tanh] +dt_funcs = [dt.math.sinh, dt.math.cosh, dt.math.tanh] + +@pytest.mark.parametrize("math_func, dt_func", zip(funcs, dt_funcs)) +def test_dt_hyperbolic1(math_func, dt_func): + srcs = srcs_bool + srcs_int[:2] + DT = dt.Frame(srcs) + RES = DT[:, dt_func(f[:])] + frame_integrity_check(RES) + assert RES.to_list() == [[hyperbolic_func(math_func, x) for x in src] for src in srcs] + +def test_dt_hyperbolic_acosh(): + srcs = [[7, 56, 2.45, 1]] + DT = dt.Frame(srcs) + RES = DT[:, dt.math.arcosh(f[:])] + frame_integrity_check(RES) + assert RES.to_list() == [[hyperbolic_func(math.acosh, x) for x in src] for src in srcs] + +def test_dt_hyperbolic_atanh(): + srcs = [[0.59, -0.12, 0.00008]] + DT = dt.Frame(srcs) + RES = DT[:, dt.math.artanh(f[:])] + frame_integrity_check(RES) + assert RES.to_list() == [[hyperbolic_func(math.atanh, x) for x in src] for src in srcs] + +def test_dt_hyperbolic_asinh(): + srcs = [[0.59, -0.12, 0.00008]] + DT = dt.Frame(srcs) + RES = DT[:, dt.math.arsinh(f[:])] + frame_integrity_check(RES) + assert RES.to_list() == [[hyperbolic_func(math.asinh, x) for x in src] for src in srcs] + +funcs = [math.sinh, math.cosh, math.tanh, math.acosh, math.asinh, math.atanh] +funcs = product(dt_funcs, srcs_str) +@pytest.mark.parametrize("dt_func, src", funcs) +def test_dt_hyperbolic_invalid(dt_func, src): + DT = dt.Frame(src) + col_stype = DT.stype.name + fn_name = dt_func.__name__ + with pytest.raises(TypeError, match=f"Function {fn_name} cannot be applied to a " + f"column of type {col_stype}"): + assert DT[:, dt_func(f[0])] \ No newline at end of file From 52f6f7317e9ae61e08d3a58fbd1ad0418ab75c59 Mon Sep 17 00:00:00 2001 From: samukweku Date: Mon, 3 Apr 2023 20:56:22 +1000 Subject: [PATCH 6/8] use integers --- tests/ijby/test-func-unary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ijby/test-func-unary.py b/tests/ijby/test-func-unary.py index a85fd14c97..02aa2b9d91 100644 --- a/tests/ijby/test-func-unary.py +++ b/tests/ijby/test-func-unary.py @@ -244,7 +244,7 @@ def test_dt_hyperbolic1(math_func, dt_func): assert RES.to_list() == [[hyperbolic_func(math_func, x) for x in src] for src in srcs] def test_dt_hyperbolic_acosh(): - srcs = [[7, 56, 2.45, 1]] + srcs = [[7, 56, 3, 1]] DT = dt.Frame(srcs) RES = DT[:, dt.math.arcosh(f[:])] frame_integrity_check(RES) From 16216e4896e521b3d57996388ea3353bc46e2ded Mon Sep 17 00:00:00 2001 From: samukweku Date: Mon, 3 Apr 2023 20:57:11 +1000 Subject: [PATCH 7/8] add comments --- tests/ijby/test-func-unary.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ijby/test-func-unary.py b/tests/ijby/test-func-unary.py index 02aa2b9d91..13b5e8dd9f 100644 --- a/tests/ijby/test-func-unary.py +++ b/tests/ijby/test-func-unary.py @@ -244,6 +244,8 @@ def test_dt_hyperbolic1(math_func, dt_func): assert RES.to_list() == [[hyperbolic_func(math_func, x) for x in src] for src in srcs] def test_dt_hyperbolic_acosh(): + # floating point might have different precision + # from python, hence the use of integers srcs = [[7, 56, 3, 1]] DT = dt.Frame(srcs) RES = DT[:, dt.math.arcosh(f[:])] From 8c284178bf1ac9bbcf876ecc6e2487ebe5c1686a Mon Sep 17 00:00:00 2001 From: samukweku Date: Mon, 3 Apr 2023 23:11:33 +1000 Subject: [PATCH 8/8] update tests --- tests/ijby/test-func-unary.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/ijby/test-func-unary.py b/tests/ijby/test-func-unary.py index 13b5e8dd9f..a57ac91601 100644 --- a/tests/ijby/test-func-unary.py +++ b/tests/ijby/test-func-unary.py @@ -244,9 +244,7 @@ def test_dt_hyperbolic1(math_func, dt_func): assert RES.to_list() == [[hyperbolic_func(math_func, x) for x in src] for src in srcs] def test_dt_hyperbolic_acosh(): - # floating point might have different precision - # from python, hence the use of integers - srcs = [[7, 56, 3, 1]] + srcs = [[7, 3, 1]] DT = dt.Frame(srcs) RES = DT[:, dt.math.arcosh(f[:])] frame_integrity_check(RES)