diff --git a/poincare/Makefile b/poincare/Makefile index 2b635dcdb..542dfcdd2 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -17,6 +17,7 @@ objs += $(addprefix poincare/src/,\ global_context.o\ hyperbolic_cosine.o\ hyperbolic_sine.o\ + hyperbolic_tangent.o\ integer.o\ integral.o\ list_data.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index c228f50b3..351162662 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index c06d693f2..517538fb1 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -17,6 +17,7 @@ class Expression { Float, HyperbolicCosine, HyperbolicSine, + HyperbolicTangent, Integer, Integral, Logarithm, diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h new file mode 100644 index 000000000..6db771ed9 --- /dev/null +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -0,0 +1,16 @@ +#ifndef POINCARE_HYPERBOLIC_TANGENT_H +#define POINCARE_HYPERBOLIC_TANGENT_H + +#include + +class HyperbolicTangent : public Function { +public: + HyperbolicTangent(); + float approximate(Context & context, AngleUnit angleUnit = AngleUnit::Radian) const override; + Type type() const override; + Expression * cloneWithDifferentOperands(Expression ** newOperands, + int numberOfOperands, bool cloneOperands = true) const override; + Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override; +}; + +#endif diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index b94d4501a..e9bddd8ec 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -93,6 +93,7 @@ cos { poincare_expression_yylval.expression = new Cosine(); return FUNCTION; } cosh { poincare_expression_yylval.expression = new HyperbolicCosine(); return FUNCTION; } int { poincare_expression_yylval.expression = new Integral(); return FUNCTION; } tan { poincare_expression_yylval.expression = new Tangent(); return FUNCTION; } +tanh { poincare_expression_yylval.expression = new HyperbolicTangent(); return FUNCTION; } log { poincare_expression_yylval.expression = new Logarithm(); return FUNCTION; } ln { poincare_expression_yylval.expression = new NaperianLogarithm(); return FUNCTION; } root { poincare_expression_yylval.expression = new NthRoot(); return FUNCTION; } diff --git a/poincare/src/hyperbolic_tangent.cpp b/poincare/src/hyperbolic_tangent.cpp new file mode 100644 index 000000000..d122e99fd --- /dev/null +++ b/poincare/src/hyperbolic_tangent.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include +extern "C" { +#include +#include +} + +HyperbolicTangent::HyperbolicTangent() : + Function("tanh") +{ +} + +Expression::Type HyperbolicTangent::type() const { + return Type::HyperbolicTangent; +} + +Expression * HyperbolicTangent::cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands) const { + assert(numberOfOperands == 1); + assert(newOperands != nullptr); + HyperbolicTangent * ht = new HyperbolicTangent(); + ht->setArgument(newOperands, numberOfOperands, cloneOperands); + return ht; +} + +float HyperbolicTangent::approximate(Context& context, AngleUnit angleUnit) const { + return (expf(m_args[0]->approximate(context, angleUnit))-expf(-m_args[0]->approximate(context, angleUnit)))/ + (expf(m_args[0]->approximate(context, angleUnit))+expf(-m_args[0]->approximate(context, angleUnit))); +} + +Expression * HyperbolicTangent::evaluate(Context& context, AngleUnit angleUnit) const { + Expression * evaluation = m_args[0]->evaluate(context, angleUnit); + assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex); + if (evaluation->type() == Type::Matrix) { + delete evaluation; + return new Complex(NAN); + } + Expression * arguments[2]; + arguments[0] = new HyperbolicSine(); + ((Function *)arguments[0])->setArgument(&evaluation, 1, true); + arguments[1] = new HyperbolicCosine(); + ((Function *)arguments[1])->setArgument(&evaluation, 1, true); + delete evaluation; + Expression * result = new Fraction(arguments, true); + delete arguments[1]; + delete arguments[0]; + Expression * resultEvaluation = result->evaluate(context, angleUnit); + delete result; + return resultEvaluation; +}