From 5d93c7244b31dbed511e4d4c2c52762d84e836d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 3 Feb 2017 11:43:03 +0100 Subject: [PATCH] [poincare] Implement complex evaluation of trigonometric functions Change-Id: Icb8141dde4b5ead4366c4aac006e9b3e4713b77a --- poincare/include/poincare/cosine.h | 1 + poincare/include/poincare/sine.h | 1 + poincare/include/poincare/tangent.h | 1 + poincare/src/cosine.cpp | 20 ++++++++++++++++++-- poincare/src/sine.cpp | 27 +++++++++++++++++++++++++-- poincare/src/tangent.cpp | 26 ++++++++++++++++++++++++-- 6 files changed, 70 insertions(+), 6 deletions(-) diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 3460a9224..f781985bc 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -10,6 +10,7 @@ public: 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/include/poincare/sine.h b/poincare/include/poincare/sine.h index 4c0a13de7..9801c68c6 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -10,6 +10,7 @@ public: 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/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 80e4e0f56..8ce89d3c2 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -10,6 +10,7 @@ public: Type type() const override; Expression * cloneWithDifferentOperands(Expression ** newOperands, int numnerOfOperands, bool cloneOperands = true) const override; + Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override; }; #endif diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 7528f4ca3..0c2933194 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -1,5 +1,6 @@ #include - +#include +#include extern "C" { #include #include @@ -30,4 +31,19 @@ float Cosine::approximate(Context& context, AngleUnit angleUnit) const { return cosf(m_args[0]->approximate(context, angleUnit)); } -//TODO: implement evaluate to handle cos complex \ No newline at end of file +Expression * Cosine::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 * arg = new Complex(-((Complex *)evaluation)->b(), ((Complex *)evaluation)->a()); + Function * cosh = new HyperbolicCosine(); + cosh->setArgument(&arg, 1, true); + delete evaluation; + delete arg; + Expression * resultEvaluation = cosh->evaluate(context, angleUnit); + delete cosh; + return resultEvaluation; +} diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index ff7decd7f..1c07dc597 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -1,5 +1,7 @@ #include - +#include +#include +#include extern "C" { #include #include @@ -30,4 +32,25 @@ float Sine::approximate(Context& context, AngleUnit angleUnit) const { return sinf(m_args[0]->approximate(context, angleUnit)); } -//TODO: implement evaluate to handle sin complex \ No newline at end of file +Expression * Sine::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 * arg = new Complex(-((Complex *)evaluation)->b(), ((Complex *)evaluation)->a()); + Function * sinh = new HyperbolicSine(); + sinh->setArgument(&arg, 1, true); + delete evaluation; + delete arg; + Expression * args[2]; + args[0] = new Complex(0.0f, -1.0f); + args[1] = sinh; + Multiplication * result = new Multiplication(args, true); + delete args[0]; + delete args[1]; + Expression * resultEvaluation = result->evaluate(context, angleUnit); + delete result; + return resultEvaluation; +} diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 80449d812..75e288edb 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -1,5 +1,8 @@ #include - +#include +#include +#include +#include extern "C" { #include #include @@ -30,4 +33,23 @@ float Tangent::approximate(Context& context, AngleUnit angleUnit) const { return tanf(m_args[0]->approximate(context, angleUnit)); } -//TODO: implement evaluate to handle tan complex \ No newline at end of file +Expression * Tangent::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 Sine(); + ((Function *)arguments[0])->setArgument(&evaluation, 1, true); + arguments[1] = new Cosine(); + ((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; +}