[poincare] Implement cos/acos in degree in complex domain

This commit is contained in:
Émilie Feral
2018-04-25 17:28:33 +02:00
parent d89b6ef85a
commit 175c070dd1
12 changed files with 34 additions and 49 deletions

View File

@@ -4,6 +4,7 @@
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/approximation_engine.h>
#include <poincare/trigonometry.h>
namespace Poincare {
@@ -26,7 +27,9 @@ private:
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit);
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
return Trigonometry::computeInverseOnComplex(c, angleUnit, std::acos);
}
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}

View File

@@ -4,6 +4,7 @@
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/approximation_engine.h>
#include <poincare/trigonometry.h>
namespace Poincare {
@@ -24,7 +25,9 @@ private:
/* Simplification */
Expression * shallowReduce(Context & context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit);
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
return Trigonometry::computeInverseOnComplex(c, angleUnit, std::asin);
}
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit, computeOnComplex<float>);
}

View File

@@ -4,6 +4,7 @@
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/approximation_engine.h>
#include <poincare/trigonometry.h>
namespace Poincare {
@@ -24,7 +25,9 @@ private:
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit);
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
return Trigonometry::computeInverseOnComplex(c, angleUnit, std::atan);
}
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}

View File

@@ -17,7 +17,7 @@ public:
Expression * clone() const override;
float characteristicXRange(Context & context, AngleUnit angleUnit) const override;
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit = AngleUnit::Radian) {
return Trigonometry::computeOnComplex(c, angleUnit, std::cos);
return Trigonometry::computeDirectOnComplex(c, angleUnit, std::cos);
}
private:
/* Layout */

View File

@@ -28,7 +28,7 @@ public:
template<typename T>
class Complex : public std::complex<T>, public Evaluation<T> {
public:
Complex(T a, T b = 0.0) : std::complex<T>(a, b) {}
Complex(T a, T b = -0.0) : std::complex<T>(a, b) {}
Complex(std::complex<T> c) : std::complex<T>(c) {}
static Complex Undefined() {
return Complex(NAN, NAN);

View File

@@ -16,7 +16,7 @@ public:
Type type() const override;
Expression * clone() const override;
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit = AngleUnit::Radian) {
return Trigonometry::computeOnComplex(c, angleUnit, std::sin);
return Trigonometry::computeDirectOnComplex(c, angleUnit, std::sin);
}
private:
/* Layout */

View File

@@ -27,7 +27,7 @@ private:
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit = AngleUnit::Radian) {
return Trigonometry::computeOnComplex(c, angleUnit, std::tan);
return Trigonometry::computeDirectOnComplex(c, angleUnit, std::tan);
}
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);

View File

@@ -18,7 +18,8 @@ public:
constexpr static int k_numberOfEntries = 37;
static Expression * table(const Expression * e, Expression::Type type, Context & context, Expression::AngleUnit angleUnit); // , Function f, bool inverse
template <typename T> using Approximation = std::complex<T> (*)(const std::complex<T>&);
template <typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate);
template <typename T> static std::complex<T> computeDirectOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate);
template <typename T> static std::complex<T> computeInverseOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate);
};
}

View File

@@ -30,13 +30,4 @@ Expression * ArcCosine::shallowReduce(Context& context, AngleUnit angleUnit) {
return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit);
}
template<typename T>
std::complex<T> ArcCosine::computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
std::complex<T> result = std::acos(c);
if (angleUnit == AngleUnit::Degree && result.imag() == 0.0) {
result *= 180/M_PI;
}
return result;
}
}

View File

@@ -30,13 +30,4 @@ Expression * ArcSine::shallowReduce(Context& context, AngleUnit angleUnit) {
return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit);
}
template<typename T>
std::complex<T> ArcSine::computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
std::complex<T> result = std::asin(c);
if (angleUnit == AngleUnit::Degree && result.imag() == 0.0) {
result *= 180/M_PI;
}
return result;
}
}

View File

@@ -30,13 +30,4 @@ Expression * ArcTangent::shallowReduce(Context& context, AngleUnit angleUnit) {
return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit);
}
template<typename T>
std::complex<T> ArcTangent::computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
std::complex<T> result = std::atan(c);
if (angleUnit == AngleUnit::Degree && result.imag() == 0.0) {
result *= 180/M_PI;
}
return result;
}
}

View File

@@ -49,10 +49,7 @@ Expression * Trigonometry::shallowReduceDirectFunction(Expression * e, Context&
}
Expression::Type correspondingType = e->type() == Expression::Type::Cosine ? Expression::Type::ArcCosine : (e->type() == Expression::Type::Sine ? Expression::Type::ArcSine : Expression::Type::ArcTangent);
if (e->operand(0)->type() == correspondingType) {
float trigoOp = e->operand(0)->operand(0)->approximateToScalar<float>(context, angleUnit);
if (e->type() == Expression::Type::Tangent || (trigoOp >= -1.0f && trigoOp <= 1.0f)) {
return e->replaceWith(e->editableOperand(0)->editableOperand(0), true);
}
return e->replaceWith(e->editableOperand(0)->editableOperand(0), true);
}
if (e->operand(0)->sign() == Expression::Sign::Negative) {
Expression * op = e->editableOperand(0);
@@ -109,12 +106,6 @@ bool Trigonometry::ExpressionIsEquivalentToTangent(const Expression * e) {
Expression * Trigonometry::shallowReduceInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) {
assert(e->type() == Expression::Type::ArcCosine || e->type() == Expression::Type::ArcSine || e->type() == Expression::Type::ArcTangent);
if (e->type() != Expression::Type::ArcTangent) {
float approxOp = e->operand(0)->approximateToScalar<float>(context, angleUnit);
if (approxOp > 1.0f || approxOp < -1.0f) {
return e->replaceWith(new Undefined(), true);
}
}
Expression::Type correspondingType = e->type() == Expression::Type::ArcCosine ? Expression::Type::Cosine : (e->type() == Expression::Type::ArcSine ? Expression::Type::Sine : Expression::Type::Tangent);
float pi = angleUnit == Expression::AngleUnit::Radian ? M_PI : 180;
if (e->operand(0)->type() == correspondingType) {
@@ -239,9 +230,9 @@ Expression * Trigonometry::table(const Expression * e, Expression::Type type, Co
}
template <typename T>
std::complex<T> Trigonometry::computeOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate) {
std::complex<T> Trigonometry::computeDirectOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate) {
std::complex<T> input(c);
if (angleUnit == Expression::AngleUnit::Degree && input.imag() == 0.0) {
if (angleUnit == Expression::AngleUnit::Degree) {
input = input*std::complex<T>(M_PI/180.0);
}
std::complex<T> result = approximate(input);
@@ -261,7 +252,18 @@ std::complex<T> Trigonometry::computeOnComplex(const std::complex<T> c, Expressi
return result;
}
template std::complex<double> Trigonometry::computeOnComplex<double>(const std::complex<double>, Expression::AngleUnit, Approximation<double>);
template std::complex<float> Trigonometry::computeOnComplex<float>(const std::complex<float>, Expression::AngleUnit, Approximation<float>);
template<typename T>
std::complex<T> Trigonometry::computeInverseOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate) {
std::complex<T> result = approximate(c);
if (angleUnit == Expression::AngleUnit::Degree) {
result *= 180/M_PI;
}
return result;
}
template std::complex<double> Trigonometry::computeDirectOnComplex<double>(const std::complex<double>, Expression::AngleUnit, Approximation<double>);
template std::complex<float> Trigonometry::computeDirectOnComplex<float>(const std::complex<float>, Expression::AngleUnit, Approximation<float>);
template std::complex<double> Trigonometry::computeInverseOnComplex<double>(const std::complex<double>, Expression::AngleUnit, Approximation<double>);
template std::complex<float> Trigonometry::computeInverseOnComplex<float>(const std::complex<float>, Expression::AngleUnit, Approximation<float>);
}