From 89e1597f10a84721d93f5bc91eafbc047e6ccc4e Mon Sep 17 00:00:00 2001 From: krippner <3984755+krippner@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:39:12 +0200 Subject: [PATCH] Add trigonometric and hyperbolic scalar functions --- docs/modules/basic.md | 12 +++---- include/AutoDiff/src/Basic/ops/ArcCos.hpp | 44 +++++++++++++++++++++++ include/AutoDiff/src/Basic/ops/ArcCot.hpp | 44 +++++++++++++++++++++++ include/AutoDiff/src/Basic/ops/ArcSin.hpp | 44 +++++++++++++++++++++++ include/AutoDiff/src/Basic/ops/ArcTan.hpp | 44 +++++++++++++++++++++++ include/AutoDiff/src/Basic/ops/Cosh.hpp | 42 ++++++++++++++++++++++ include/AutoDiff/src/Basic/ops/Cot.hpp | 44 +++++++++++++++++++++++ include/AutoDiff/src/Basic/ops/Sinh.hpp | 42 ++++++++++++++++++++++ include/AutoDiff/src/Basic/ops/Tan.hpp | 44 +++++++++++++++++++++++ include/AutoDiff/src/Basic/ops/Tanh.hpp | 44 +++++++++++++++++++++++ tests/Basic/CMakeLists.txt | 9 +++++ tests/Basic/testArcCos.cpp | 10 ++++++ tests/Basic/testArcCot.cpp | 10 ++++++ tests/Basic/testArcSin.cpp | 10 ++++++ tests/Basic/testArcTan.cpp | 10 ++++++ tests/Basic/testCosh.cpp | 10 ++++++ tests/Basic/testCot.cpp | 10 ++++++ tests/Basic/testSinh.cpp | 10 ++++++ tests/Basic/testTan.cpp | 10 ++++++ tests/Basic/testTanh.cpp | 10 ++++++ 20 files changed, 497 insertions(+), 6 deletions(-) create mode 100644 include/AutoDiff/src/Basic/ops/ArcCos.hpp create mode 100644 include/AutoDiff/src/Basic/ops/ArcCot.hpp create mode 100644 include/AutoDiff/src/Basic/ops/ArcSin.hpp create mode 100644 include/AutoDiff/src/Basic/ops/ArcTan.hpp create mode 100644 include/AutoDiff/src/Basic/ops/Cosh.hpp create mode 100644 include/AutoDiff/src/Basic/ops/Cot.hpp create mode 100644 include/AutoDiff/src/Basic/ops/Sinh.hpp create mode 100644 include/AutoDiff/src/Basic/ops/Tan.hpp create mode 100644 include/AutoDiff/src/Basic/ops/Tanh.hpp create mode 100644 tests/Basic/testArcCos.cpp create mode 100644 tests/Basic/testArcCot.cpp create mode 100644 tests/Basic/testArcSin.cpp create mode 100644 tests/Basic/testArcTan.cpp create mode 100644 tests/Basic/testCosh.cpp create mode 100644 tests/Basic/testCot.cpp create mode 100644 tests/Basic/testSinh.cpp create mode 100644 tests/Basic/testTan.cpp create mode 100644 tests/Basic/testTanh.cpp diff --git a/docs/modules/basic.md b/docs/modules/basic.md index 6ca358c..70848b0 100644 --- a/docs/modules/basic.md +++ b/docs/modules/basic.md @@ -44,12 +44,12 @@ x + 3; // right-hand side literal The following operations are currently supported: - `+`, `-`, `*`, `/`: Arithmetic operations. -- `pow`: Power function. -- `sin`: Sine function. -- `cos`: Cosine function. +- `sin`, `cos`, `tan`, `cot`: Trigonometric functions. +- `asin`, `acos`, `atan`, `acot`: Inverse trigonometric functions. +- `sinh`, `cosh`, `tanh`: Hyperbolic functions. - `exp`: Exponential function. - `log`: Natural logarithm. -- `sqrt`: Square root. +- `pow`: Power function. - `square`: Square function. -- `min`: Minimum of a scalar expression and zero. -- `max`: Maximum of a scalar expression and zero. +- `sqrt`: Square root. +- `min`, `max`: Minimum, maximum of a scalar expression and zero. diff --git a/include/AutoDiff/src/Basic/ops/ArcCos.hpp b/include/AutoDiff/src/Basic/ops/ArcCos.hpp new file mode 100644 index 0000000..2cb3a26 --- /dev/null +++ b/include/AutoDiff/src/Basic/ops/ArcCos.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2024 Matthias Krippner +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#ifndef AUTODIFF_SRC_BASIC_OPS_ARC_COS_HPP +#define AUTODIFF_SRC_BASIC_OPS_ARC_COS_HPP + +namespace AutoDiff::Basic { + +template +class ArcCos : public UnaryOperation, X> { +public: + using Base = UnaryOperation, X>; + using Base::Base; + + [[nodiscard]] auto _valueImpl() -> decltype(auto) + { + return std::acos(Base::xValue()); + } + + [[nodiscard]] auto _pushForwardImpl() -> decltype(auto) + { + auto const& x = Base::xValue(); + return -std::pow(1 - x * x, -0.5) * Base::xPushForward(); + } + + template + void _pullBackImpl(Derivative const& derivative) + { + auto const& x = Base::xValue(); + Base::xPullBack(derivative * (-std::pow(1 - x * x, -0.5))); + } +}; + +} // namespace AutoDiff::Basic + +namespace AutoDiff { + +AUTODIFF_MAKE_BASIC_UNARY_OP(acos, Basic::ArcCos) + +} // namespace AutoDiff + +#endif // AUTODIFF_SRC_BASIC_OPS_ARC_COS_HPP diff --git a/include/AutoDiff/src/Basic/ops/ArcCot.hpp b/include/AutoDiff/src/Basic/ops/ArcCot.hpp new file mode 100644 index 0000000..6701cf9 --- /dev/null +++ b/include/AutoDiff/src/Basic/ops/ArcCot.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2024 Matthias Krippner +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#ifndef AUTODIFF_SRC_BASIC_OPS_ARC_COT_HPP +#define AUTODIFF_SRC_BASIC_OPS_ARC_COT_HPP + +namespace AutoDiff::Basic { + +template +class ArcCot : public UnaryOperation, X> { +public: + using Base = UnaryOperation, X>; + using Base::Base; + + [[nodiscard]] auto _valueImpl() -> decltype(auto) + { + return std::atan(1 / Base::xValue()); + } + + [[nodiscard]] auto _pushForwardImpl() -> decltype(auto) + { + auto const& x = Base::xValue(); + return -1 / (1 + x * x) * Base::xPushForward(); + } + + template + void _pullBackImpl(Derivative const& derivative) + { + auto const& x = Base::xValue(); + Base::xPullBack(derivative / -(1 + x * x)); + } +}; + +} // namespace AutoDiff::Basic + +namespace AutoDiff { + +AUTODIFF_MAKE_BASIC_UNARY_OP(acot, Basic::ArcCot) + +} // namespace AutoDiff + +#endif // AUTODIFF_SRC_BASIC_OPS_ARC_COT_HPP diff --git a/include/AutoDiff/src/Basic/ops/ArcSin.hpp b/include/AutoDiff/src/Basic/ops/ArcSin.hpp new file mode 100644 index 0000000..d693305 --- /dev/null +++ b/include/AutoDiff/src/Basic/ops/ArcSin.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2024 Matthias Krippner +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#ifndef AUTODIFF_SRC_BASIC_OPS_ARC_SIN_HPP +#define AUTODIFF_SRC_BASIC_OPS_ARC_SIN_HPP + +namespace AutoDiff::Basic { + +template +class ArcSin : public UnaryOperation, X> { +public: + using Base = UnaryOperation, X>; + using Base::Base; + + [[nodiscard]] auto _valueImpl() -> decltype(auto) + { + return std::asin(Base::xValue()); + } + + [[nodiscard]] auto _pushForwardImpl() -> decltype(auto) + { + auto const& x = Base::xValue(); + return std::pow(1 - x * x, -0.5) * Base::xPushForward(); + } + + template + void _pullBackImpl(Derivative const& derivative) + { + auto const& x = Base::xValue(); + Base::xPullBack(derivative * std::pow(1 - x * x, -0.5)); + } +}; + +} // namespace AutoDiff::Basic + +namespace AutoDiff { + +AUTODIFF_MAKE_BASIC_UNARY_OP(asin, Basic::ArcSin) + +} // namespace AutoDiff + +#endif // AUTODIFF_SRC_BASIC_OPS_ARC_SIN_HPP diff --git a/include/AutoDiff/src/Basic/ops/ArcTan.hpp b/include/AutoDiff/src/Basic/ops/ArcTan.hpp new file mode 100644 index 0000000..2797cdf --- /dev/null +++ b/include/AutoDiff/src/Basic/ops/ArcTan.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2024 Matthias Krippner +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#ifndef AUTODIFF_SRC_BASIC_OPS_ARC_TAN_HPP +#define AUTODIFF_SRC_BASIC_OPS_ARC_TAN_HPP + +namespace AutoDiff::Basic { + +template +class ArcTan : public UnaryOperation, X> { +public: + using Base = UnaryOperation, X>; + using Base::Base; + + [[nodiscard]] auto _valueImpl() -> decltype(auto) + { + return std::atan(Base::xValue()); + } + + [[nodiscard]] auto _pushForwardImpl() -> decltype(auto) + { + auto const& x = Base::xValue(); + return 1 / (1 + x * x) * Base::xPushForward(); + } + + template + void _pullBackImpl(Derivative const& derivative) + { + auto const& x = Base::xValue(); + Base::xPullBack(derivative / (1 + x * x)); + } +}; + +} // namespace AutoDiff::Basic + +namespace AutoDiff { + +AUTODIFF_MAKE_BASIC_UNARY_OP(atan, Basic::ArcTan) + +} // namespace AutoDiff + +#endif // AUTODIFF_SRC_BASIC_OPS_ARC_TAN_HPP diff --git a/include/AutoDiff/src/Basic/ops/Cosh.hpp b/include/AutoDiff/src/Basic/ops/Cosh.hpp new file mode 100644 index 0000000..80d6e22 --- /dev/null +++ b/include/AutoDiff/src/Basic/ops/Cosh.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2024 Matthias Krippner +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#ifndef AUTODIFF_SRC_BASIC_OPS_COSH_HPP +#define AUTODIFF_SRC_BASIC_OPS_COSH_HPP + +namespace AutoDiff::Basic { + +template +class Cosh : public UnaryOperation, X> { +public: + using Base = UnaryOperation, X>; + using Base::Base; + + [[nodiscard]] auto _valueImpl() -> decltype(auto) + { + return std::cosh(Base::xValue()); + } + + [[nodiscard]] auto _pushForwardImpl() -> decltype(auto) + { + return std::sinh(Base::xValue()) * Base::xPushForward(); + } + + template + void _pullBackImpl(Derivative const& derivative) + { + Base::xPullBack(derivative * std::sinh(Base::xValue())); + } +}; + +} // namespace AutoDiff::Basic + +namespace AutoDiff { + +AUTODIFF_MAKE_BASIC_UNARY_OP(cosh, Basic::Cosh) + +} // namespace AutoDiff + +#endif // AUTODIFF_SRC_BASIC_OPS_COSH_HPP diff --git a/include/AutoDiff/src/Basic/ops/Cot.hpp b/include/AutoDiff/src/Basic/ops/Cot.hpp new file mode 100644 index 0000000..8357714 --- /dev/null +++ b/include/AutoDiff/src/Basic/ops/Cot.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2024 Matthias Krippner +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#ifndef AUTODIFF_SRC_BASIC_OPS_COT_HPP +#define AUTODIFF_SRC_BASIC_OPS_COT_HPP + +namespace AutoDiff::Basic { + +template +class Cot : public UnaryOperation, X> { +public: + using Base = UnaryOperation, X>; + using Base::Base; + + [[nodiscard]] auto _valueImpl() -> decltype(auto) + { + return 1 / std::tan(Base::xValue()); + } + + [[nodiscard]] auto _pushForwardImpl() -> decltype(auto) + { + auto const& tan_x = std::tan(Base::xValue()); + return (-1 - 1 / (tan_x * tan_x)) * Base::xPushForward(); + } + + template + void _pullBackImpl(Derivative const& derivative) + { + auto const& tan_x = std::tan(Base::xValue()); + Base::xPullBack(derivative * (-1 - 1 / (tan_x * tan_x))); + } +}; + +} // namespace AutoDiff::Basic + +namespace AutoDiff { + +AUTODIFF_MAKE_BASIC_UNARY_OP(cot, Basic::Cot) + +} // namespace AutoDiff + +#endif // AUTODIFF_SRC_BASIC_OPS_COT_HPP diff --git a/include/AutoDiff/src/Basic/ops/Sinh.hpp b/include/AutoDiff/src/Basic/ops/Sinh.hpp new file mode 100644 index 0000000..af170b8 --- /dev/null +++ b/include/AutoDiff/src/Basic/ops/Sinh.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2024 Matthias Krippner +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#ifndef AUTODIFF_SRC_BASIC_OPS_SINH_HPP +#define AUTODIFF_SRC_BASIC_OPS_SINH_HPP + +namespace AutoDiff::Basic { + +template +class Sinh : public UnaryOperation, X> { +public: + using Base = UnaryOperation, X>; + using Base::Base; + + [[nodiscard]] auto _valueImpl() -> decltype(auto) + { + return std::sinh(Base::xValue()); + } + + [[nodiscard]] auto _pushForwardImpl() -> decltype(auto) + { + return std::cosh(Base::xValue()) * Base::xPushForward(); + } + + template + void _pullBackImpl(Derivative const& derivative) + { + Base::xPullBack(derivative * std::cosh(Base::xValue())); + } +}; + +} // namespace AutoDiff::Basic + +namespace AutoDiff { + +AUTODIFF_MAKE_BASIC_UNARY_OP(sinh, Basic::Sinh) + +} // namespace AutoDiff + +#endif // AUTODIFF_SRC_BASIC_OPS_SINH_HPP diff --git a/include/AutoDiff/src/Basic/ops/Tan.hpp b/include/AutoDiff/src/Basic/ops/Tan.hpp new file mode 100644 index 0000000..a1e693a --- /dev/null +++ b/include/AutoDiff/src/Basic/ops/Tan.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2024 Matthias Krippner +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#ifndef AUTODIFF_SRC_BASIC_OPS_TAN_HPP +#define AUTODIFF_SRC_BASIC_OPS_TAN_HPP + +namespace AutoDiff::Basic { + +template +class Tan : public UnaryOperation, X> { +public: + using Base = UnaryOperation, X>; + using Base::Base; + + [[nodiscard]] auto _valueImpl() -> decltype(auto) + { + return std::tan(Base::xValue()); + } + + [[nodiscard]] auto _pushForwardImpl() -> decltype(auto) + { + auto const& tan_x = std::tan(Base::xValue()); + return (1 + tan_x * tan_x) * Base::xPushForward(); + } + + template + void _pullBackImpl(Derivative const& derivative) + { + auto const& tan_x = std::tan(Base::xValue()); + Base::xPullBack(derivative * (1 + tan_x * tan_x)); + } +}; + +} // namespace AutoDiff::Basic + +namespace AutoDiff { + +AUTODIFF_MAKE_BASIC_UNARY_OP(tan, Basic::Tan) + +} // namespace AutoDiff + +#endif // AUTODIFF_SRC_BASIC_OPS_TAN_HPP diff --git a/include/AutoDiff/src/Basic/ops/Tanh.hpp b/include/AutoDiff/src/Basic/ops/Tanh.hpp new file mode 100644 index 0000000..573d6db --- /dev/null +++ b/include/AutoDiff/src/Basic/ops/Tanh.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2024 Matthias Krippner +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#ifndef AUTODIFF_SRC_BASIC_OPS_TANH_HPP +#define AUTODIFF_SRC_BASIC_OPS_TANH_HPP + +namespace AutoDiff::Basic { + +template +class Tanh : public UnaryOperation, X> { +public: + using Base = UnaryOperation, X>; + using Base::Base; + + [[nodiscard]] auto _valueImpl() -> decltype(auto) + { + return std::tanh(Base::xValue()); + } + + [[nodiscard]] auto _pushForwardImpl() -> decltype(auto) + { + auto const& tanh_x = std::tanh(Base::xValue()); + return (1 - tanh_x * tanh_x) * Base::xPushForward(); + } + + template + void _pullBackImpl(Derivative const& derivative) + { + auto const& tanh_x = std::tanh(Base::xValue()); + Base::xPullBack(derivative * (1 - tanh_x * tanh_x)); + } +}; + +} // namespace AutoDiff::Basic + +namespace AutoDiff { + +AUTODIFF_MAKE_BASIC_UNARY_OP(tanh, Basic::Tanh) + +} // namespace AutoDiff + +#endif // AUTODIFF_SRC_BASIC_OPS_TANH_HPP diff --git a/tests/Basic/CMakeLists.txt b/tests/Basic/CMakeLists.txt index 919b351..9923232 100644 --- a/tests/Basic/CMakeLists.txt +++ b/tests/Basic/CMakeLists.txt @@ -1,5 +1,11 @@ add_executable(BasicTests + testArcCos.cpp + testArcSin.cpp + testArcTan.cpp + testArcCot.cpp testCos.cpp + testCot.cpp + testCosh.cpp testDifference.cpp testExp.cpp testLog.cpp @@ -10,9 +16,12 @@ add_executable(BasicTests testProduct.cpp testQuotient.cpp testSin.cpp + testSinh.cpp testSqrt.cpp testSquare.cpp testSum.cpp + testTan.cpp + testTanh.cpp ) target_compile_features(BasicTests PRIVATE cxx_std_11) target_link_libraries(BasicTests PRIVATE Catch2::Catch2WithMain AutoDiff::AutoDiff) diff --git a/tests/Basic/testArcCos.cpp b/tests/Basic/testArcCos.cpp new file mode 100644 index 0000000..5d3f277 --- /dev/null +++ b/tests/Basic/testArcCos.cpp @@ -0,0 +1,10 @@ +#include "common.hpp" + +#include + +SCENARIO("acos(x)", "ArcCos") +{ + auto const [point, value, derivative, prec] + = GENERATE(table({{0.5, 1.047198, -1.154701, 1E-6}})); + CHECK_UNARY_OP(acos, point, value, derivative, prec); +} diff --git a/tests/Basic/testArcCot.cpp b/tests/Basic/testArcCot.cpp new file mode 100644 index 0000000..9247aae --- /dev/null +++ b/tests/Basic/testArcCot.cpp @@ -0,0 +1,10 @@ +#include "common.hpp" + +#include + +SCENARIO("acot(x)", "ArcCot") +{ + auto const [point, value, derivative, prec] + = GENERATE(table({{0.5, 1.107149, -0.8, 1E-6}})); + CHECK_UNARY_OP(acot, point, value, derivative, prec); +} diff --git a/tests/Basic/testArcSin.cpp b/tests/Basic/testArcSin.cpp new file mode 100644 index 0000000..2c6aef9 --- /dev/null +++ b/tests/Basic/testArcSin.cpp @@ -0,0 +1,10 @@ +#include "common.hpp" + +#include + +SCENARIO("asin(x)", "ArcSin") +{ + auto const [point, value, derivative, prec] + = GENERATE(table({{0.5, 0.5235988, 1.154701, 1E-6}})); + CHECK_UNARY_OP(asin, point, value, derivative, prec); +} diff --git a/tests/Basic/testArcTan.cpp b/tests/Basic/testArcTan.cpp new file mode 100644 index 0000000..73fc16f --- /dev/null +++ b/tests/Basic/testArcTan.cpp @@ -0,0 +1,10 @@ +#include "common.hpp" + +#include + +SCENARIO("atan(x)", "ArcTan") +{ + auto const [point, value, derivative, prec] + = GENERATE(table({{0.5, 0.4636476, 0.8, 1E-6}})); + CHECK_UNARY_OP(atan, point, value, derivative, prec); +} diff --git a/tests/Basic/testCosh.cpp b/tests/Basic/testCosh.cpp new file mode 100644 index 0000000..0999057 --- /dev/null +++ b/tests/Basic/testCosh.cpp @@ -0,0 +1,10 @@ +#include "common.hpp" + +#include + +SCENARIO("cosh(x)", "Cosh") +{ + auto const [point, value, derivative, prec] + = GENERATE(table({{1.0, 1.543081, 1.175201, 1E-6}})); + CHECK_UNARY_OP(cosh, point, value, derivative, prec); +} diff --git a/tests/Basic/testCot.cpp b/tests/Basic/testCot.cpp new file mode 100644 index 0000000..70a72e8 --- /dev/null +++ b/tests/Basic/testCot.cpp @@ -0,0 +1,10 @@ +#include "common.hpp" + +#include + +SCENARIO("cot(x)", "Cot") +{ + auto const [point, value, derivative, prec] + = GENERATE(table({{0.5, 1.830488, -4.350685, 1E-6}})); + CHECK_UNARY_OP(cot, point, value, derivative, prec); +} diff --git a/tests/Basic/testSinh.cpp b/tests/Basic/testSinh.cpp new file mode 100644 index 0000000..3b08bb2 --- /dev/null +++ b/tests/Basic/testSinh.cpp @@ -0,0 +1,10 @@ +#include "common.hpp" + +#include + +SCENARIO("sinh(x)", "Sinh") +{ + auto const [point, value, derivative, prec] + = GENERATE(table({{1.0, 1.175201, 1.543081, 1E-6}})); + CHECK_UNARY_OP(sinh, point, value, derivative, prec); +} diff --git a/tests/Basic/testTan.cpp b/tests/Basic/testTan.cpp new file mode 100644 index 0000000..2fa73b4 --- /dev/null +++ b/tests/Basic/testTan.cpp @@ -0,0 +1,10 @@ +#include "common.hpp" + +#include + +SCENARIO("tan(x)", "Tan") +{ + auto const [point, value, derivative, prec] + = GENERATE(table({{1.0, 1.557408, 3.425519, 1E-6}})); + CHECK_UNARY_OP(tan, point, value, derivative, prec); +} diff --git a/tests/Basic/testTanh.cpp b/tests/Basic/testTanh.cpp new file mode 100644 index 0000000..1bc0f1e --- /dev/null +++ b/tests/Basic/testTanh.cpp @@ -0,0 +1,10 @@ +#include "common.hpp" + +#include + +SCENARIO("tanh(x)", "Tanh") +{ + auto const [point, value, derivative, prec] + = GENERATE(table({{1.0, 0.7615942, 0.4199743, 1E-6}})); + CHECK_UNARY_OP(tanh, point, value, derivative, prec); +}